[recovery mode] Pool объектов для Unity3d
Все знают что операции создания и удаления объектов не дешевые. Например создавать каждый раз пулю и уничтожать, довольно накладно для тех же мобильных устройств. Может стоит не уничтожать пулю, а скрывать ее. Вот решил поделится своей реализацией Pool Manager. Который использую в разных проектах, в том числе и на photon server.СтруктурыДля начала, нужно создать интерфейс:
public interface IPoolObject
using System.Collections.Generic; using System;
public class PoolManager
public delegate bool Compare
protected Dictionary
public PoolManager (int maxInstance)
{
MaxInstances = maxInstance;
objects = new Dictionary
public virtual bool CanPush () { return InctanceCount + 1 < MaxInstances; }
public virtual bool Push (K groupKey, V value)
{
bool result = false;
if (CanPush ())
{
value.OnPush ();
if (! objects.ContainsKey (groupKey))
{
objects.Add (groupKey, new List
public virtual T Pop
public virtual T Pop
public virtual T Pop
public virtual bool Contains (K groupKey) { return objects.ContainsKey (groupKey); }
public virtual void Clear () { objects.Clear (); }
protected virtual bool ValidateForPop (Type type) { return cache.ContainsKey (type) && cache[type].Count > 0; }
protected virtual void RemoveObject (K groupKey, int idx) { if (idx >= 0 && idx < objects[groupKey].Count) { objects[groupKey].RemoveAt(idx); if (objects[groupKey].Count == 0) { objects.Remove(groupKey); } } }
protected void RemoveFromCache (V value, Type type) { if (cache.ContainsKey (type)) { cache[type].Remove (value); if (cache[type].Count == 0) { cache.Remove (type); } } } } На что стоит обратить внимание.MaxInstances — поле максимального количества pool объектов. В случае, если не возможно поместить в пул очередной объект, сам объект вывозит метод FailedPush (); OnPush () — непосредственно перед попаданием в пул.Create () — перед тем, как пул вернет нам экземпляр.
Общий Pool готов. Теперь нужно сделать вариацию для Unity3d. Приступим
using UnityEngine; using System.Collections;
public class UnityPoolManager: MonoBehaviour { public static UnityPoolManager Instance {get; protected set;}
public int maxInstanceCount = 128;
protected PoolManager
protected virtual void Awake ()
{
Instance = this;
poolManager = new PoolManager
public virtual bool CanPush () { return poolManager.CanPush (); }
public virtual bool Push (string groupKey, UnityPoolObject poolObject) { return poolManager.Push (groupKey, poolObject); }
public virtual T PopOrCreate
public virtual T PopOrCreate
public virtual UnityPoolObject Pop (string groupKey)
{
return poolManager.Pop
public virtual T Pop
public virtual T Pop
public virtual T Pop
public virtual bool Contains (string groupKey) { return poolManager.Contains (groupKey); }
public virtual void Clear () { poolManager.Clear (); }
protected virtual T CreateObject
using UnityEngine; using System.Collections;
public class UnityPoolObject: MonoBehaviour, IPoolObject
protected Transform myTransform;
protected virtual void Awake () { myTransform = transform; }
public virtual void SetTransform (Vector3 position, Quaternion rotation) { myTransform.position = position; myTransform.rotation = rotation; }
public virtual void Create () { gameObject.SetActive (true); }
public virtual void OnPush () { gameObject.SetActive (false); }
public virtual void Push () { UnityPoolManager.Instance.Push (Group, this); }
public void FailedPush () { Debug.Log («FailedPush»); // !!! Destroy (gameObject); } }
Все объекты будем наследовать от него.FailedPush () — стоит обратить внимание на этот метод. Возможно вы захотите бросать исключение, мол пул забит или что-то еще.Теперь перейдем к использованию. На примере пули следов и UI List item.
public class Bullet: UnityPoolObject
{
…
}
// создание
Bullet bullet = UnityPoolManager.Instance.PopOrCreate
/// ---
StepObject stepObject = UnityPoolManager.Instance.PopOrCreate
… profileItem.profileId = profileId; list.AddItem (profileItem);
// ---- Надеюсь данный пример поможет вам в написании своих проектов на Unity3d.