Unity Stack+GameObject.SetActive()实现对象池。

public class ObjectPoolManager : Singleton<ObjectPoolManager>
	{
		private class InternalPool
		{
			private Stack<GameObject> m_pool;
			private int m_poolDepth;
			private GameObject m_poolParent;

			public InternalPool(GameObject poolParent, int defPoolDepth)
			{
				m_pool = new Stack<GameObject>();
				m_poolParent = poolParent;
				m_poolDepth = defPoolDepth;
			}

			public void SetPoolDepthAndKeepNum(int poolDepth)
			{
				if (poolDepth == m_poolDepth)
				{
					return;
				}
				m_poolDepth = Mathf.Clamp(poolDepth, 0, 1000);
				CleanToDepthNum();
			}

			public void Release(GameObject go)
			{
				if (m_pool.Contains(go))
				{
					go.SetActive(false);
					return;
				}
				if (m_pool.Count >= m_poolDepth)
				{
					GameObject.Destroy(go);
					return;
				}
				go.SetActive(false);
				go.transform.SetParent(m_poolParent.transform);
				m_pool.Push(go);
			}

			public GameObject Get(bool setActive = true)
			{
				if (m_pool.Count > 0)
				{
					var go = m_pool.Pop();
					if (setActive)
					{
						go.SetActive(true);
					}
					go.transform.SetParent(null);
					return go;
				}

				return null;
			}

			private void CleanToDepthNum()
			{
				int keepNum = m_poolDepth;

				while (m_pool.Count > keepNum)
				{
					GameObject.Destroy(m_pool.Pop());
				}
			}

			public void Clean()
			{
				while (m_pool.Count > 0)
				{
					Object.DestroyImmediate(m_pool.Pop());
				}
			}

			public int GetCount()
			{
				return m_pool.Count;
			}
		}

		private readonly GameObject m_poolParent;
		private readonly Dictionary<string, InternalPool> m_pools;
		private readonly Dictionary<string, int> m_poolSeparateDepth;

		private int m_defaultPoolDepth;
		public int PoolDepth
		{
			get { return m_defaultPoolDepth; }
			set
			{
				m_defaultPoolDepth = value;
				m_defaultPoolDepth = Mathf.Clamp(m_defaultPoolDepth, 0, 1000);
			}
		}

		private ObjectPoolManager()
		{
			m_defaultPoolDepth = 10;
			m_pools = new Dictionary<string, InternalPool>();
			m_poolSeparateDepth = new Dictionary<string, int>();
			if (m_poolParent == null)
			{
				m_poolParent = new GameObject("PoolParent");
				GameObject.DontDestroyOnLoad(m_poolParent);
			}
		}

		public override void Dispose()
		{
			GameObject.Destroy(m_poolParent);
			m_pools.Clear();
			m_poolSeparateDepth.Clear();
			base.Dispose();
		}

		//setactive 专门为了某些需要先前置设置然后才能显示出来的对象
		public GameObject Get(string key, bool setActive = true)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				return pool.Get();
			}

			return null;
		}

		public void Release(string key, GameObject go, bool isIntoPool = true)
		{
			if (!isIntoPool)
			{
				GameObject.Destroy(go);
				return;
			}

			if (!m_pools.ContainsKey(key))
			{
				int depth = 0;
				if (!m_poolSeparateDepth.TryGetValue(key, out depth))
				{
					depth = m_defaultPoolDepth;
				}
				m_pools.Add(key, new InternalPool(m_poolParent, depth));
			}

			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				pool.Release(go);
			}
		}

		public void Clean()
		{
			List<string> keys = new List<string>(m_pools.Keys);
			for (int i = 0; i != keys.Count; ++i)
			{
				var pool = m_pools[keys[i]];
				pool.Clean();
			}
			m_poolSeparateDepth.Clear();
		}

		public int GetGameObjectNum(string key)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				return pool.GetCount();
			}

			return 0;
		}

		public void SetKeyPoolDepthAndKeepNum(string key, int poolDepth)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				pool.SetPoolDepthAndKeepNum(poolDepth);
			}
			else
			{
				if (m_poolSeparateDepth.ContainsKey(key))
				{
					m_poolSeparateDepth[key] = poolDepth;
				}
				else
				{
					m_poolSeparateDepth.Add(key, poolDepth);
				}
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/qq302756113/article/details/80104549