public interface IPoolObject<T> { T Group { get; } void Create(); void OnPush(); void FailedPush(); }
using System.Collections.Generic; using System; public class PoolManager<K, V> where V :IPoolObject<K> { public virtual int MaxInstances { get; protected set; } public virtual int InctanceCount { get { return objects.Count; } } public virtual int CacheCount { get { return cache.Count; } } public delegate bool Compare<T>(T value) where T: V; protected Dictionary<K, List<V>> objects; protected Dictionary<Type, List<V>> cache; public PoolManager(int maxInstance) { MaxInstances = maxInstance; objects = new Dictionary<K, List<V>>(); cache = new Dictionary<Type, List<V>>(); } 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<V>()); } objects[groupKey].Add(value); Type type = value.GetType(); if (!cache.ContainsKey(type)) { cache.Add(type, new List<V>()); } cache[type].Add(value); } else { value.FailedPush(); } return result; } public virtual T Pop<T>(K groupKey) where T : V { T result = default(T); if (Contains(groupKey) && objects[groupKey].Count > 0) { for (int i = 0; i < objects[groupKey].Count; i++) { if (objects[groupKey][i] is T) { result = (T)objects[groupKey][i]; Type type = result.GetType(); RemoveObject(groupKey, i); RemoveFromCache(result, type); result.Create(); break; } } } return result; } public virtual T Pop<T>() where T: V { T result = default(T); Type type = typeof(T); if (ValidateForPop(type)) { for (int i = 0; i < cache[type].Count; i++) { result = (T)cache[type][i]; if (result != null && objects.ContainsKey(result.Group)) { objects[result.Group].Remove(result); RemoveFromCache(result, type); result.Create(); break; } } } return result; } public virtual T Pop<T>(Compare<T> comparer) where T : V { T result = default(T); Type type = typeof(T); if (ValidateForPop(type)) { for(int i = 0; i < cache[type].Count; i++) { T value = (T)cache[type][i]; if (comparer(value)) { objects[value.Group].Remove(value); RemoveFromCache(result, type); result = value; result.Create(); break; } } } return result; } 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); } } } }
using UnityEngine; using System.Collections; public class UnityPoolManager : MonoBehaviour { public static UnityPoolManager Instance {get; protected set;} public int maxInstanceCount = 128; protected PoolManager<string, UnityPoolObject> poolManager; protected virtual void Awake() { Instance = this; poolManager = new PoolManager<string, UnityPoolObject>(maxInstanceCount); } public virtual bool CanPush() { return poolManager.CanPush(); } public virtual bool Push(string groupKey, UnityPoolObject poolObject) { return poolManager.Push(groupKey, poolObject); } public virtual T PopOrCreate<T>(T prefab) where T : UnityPoolObject { return PopOrCreate(prefab, Vector3.zero, Quaternion.identity); } public virtual T PopOrCreate<T>(T prefab, Vector3 position, Quaternion rotation) where T : UnityPoolObject { T result = poolManager.Pop<T>(prefab.Group); if (result == null) { result = CreateObject<T>(prefab, position, rotation); } else { result.SetTransform(position, rotation); } return result; } public virtual UnityPoolObject Pop(string groupKey) { return poolManager.Pop<UnityPoolObject>(groupKey); } public virtual T Pop<T>() where T : UnityPoolObject { return poolManager.Pop<T>(); } public virtual T Pop<T>(PoolManager<string, UnityPoolObject>.Compare<T> comparer) where T : UnityPoolObject { return poolManager.Pop<T>(comparer); } public virtual T Pop<T>(string groupKey) where T : UnityPoolObject { return poolManager.Pop<T>(groupKey); } public virtual bool Contains(string groupKey) { return poolManager.Contains(groupKey); } public virtual void Clear() { poolManager.Clear(); } protected virtual T CreateObject<T>(T prefab, Vector3 position, Quaternion rotation) where T : UnityPoolObject { GameObject go = Instantiate(prefab.gameObject, position, rotation) as GameObject; T result = go.GetComponent<T>(); result.name = prefab.name; return result; } }
using UnityEngine; using System.Collections; public class UnityPoolObject : MonoBehaviour, IPoolObject<string> { public virtual string Group { get {return name;} } // public Transform MyTransform { get { return myTransform; } } 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); } }
public class Bullet : UnityPoolObject // , { ... } // Bullet bullet = UnityPoolManager.Instance.PopOrCreate<Bullet>(bulletPrefab, bulletPoint.position, Quaternion.identity); bullet.Execute(sender, bulletPoint.position, CalculateTarget(target, accuracy01), damage, blockTime, range, bulletSpeed); ... // , // - timer-= Time.deltaTime; if (timer< 0) { Push(); }
public class StepObject : UnityPoolObject // { ... } /// StepObject stepObject = UnityPoolManager.Instance.PopOrCreate<StepObject>(prefab, sender.position, sender.rotation); FXManager.Instance.InitDecal(null, stepObject.gameObject, hit, direction); stepObject.MyTransform.rotation *= rotation; StartCoroutine(ApplyDecalC(stepObject)); /// protected virtual IEnumerator ApplyDecalC(StepObject decalObject) { yield return new WaitForSeconds(waitTime); // - yield return StartCoroutine(FXManager.Instance.HideOjectC(decalObject.gameObject, hideTime)); // decalObject.Push(); // , }
public class ProfileListItem : UnityPoolObject { ... } // - ProfileListItem profileItem = UnityPoolManager.Instance.PopOrCreate(prefab); ... // profileItem.profileId = profileId; list.AddItem(profileItem); // // , . Push foreach(ProfileListItem item in list) { item.Push(); }
Source: https://habr.com/ru/post/255499/
All Articles