/// <summary> /// Unsafe回收一个Instance。如果确定它来自pool,使用此方法更有效率。 /// 如果它不是一个instance或者它不是来自任何Pool: /// 如果destroyOnNotFromPool参数为true,就Destroy它; /// 如果destroyOnNotFromPool参数为false, /// 存在父对象,直到它自己被Destroy,或父对象被Destroy, /// 不存在父对象,直到它自己被Destroy,或切换场景被场景Destroy。 /// </summary> /// <param name="instance"></param> /// <param name="destroyNotFromPool"></param> public static void DespawnUnsafe(GameObject instance, bool destroyNotFromPool = true) { if (instance == null) { return; } ReusableObject reusable = instance.GetComponent <ReusableObject>(); if (reusable == null) { if (destroyNotFromPool) { GameObject.Destroy(instance); } } else { if (!reusable.isFromPool && destroyNotFromPool) { GameObject.Destroy(instance); } else { reusable.Despawn(true); } } }
/// <summary> /// 生成一个Instance /// </summary> /// <param name="prefab"></param> /// <param name="position"></param> /// <returns></returns> public GameObject Spawn(GameObject prefab, Vector3 position) { if (prefab == null) { Debug.LogErrorFormat("{0} -> Argument named 'prefab' is null.", poolName); return(null); } GameObject instance = GetOrCreateRecycledInstance(prefab); instance.transform.position = position; ReusableObject reusable = GetOrAddReusableObject(instance); instance.gameObject.SetActive(true); reusable.Spawn(); if (m_EditorLog) { Debug.LogFormat( "{0} -> Spawn a instance named '{1}'.", poolName, instance.name ); } return(instance); }
/// <summary> /// 添加外部Instance。要保证使用的Prefab和这里的是同一个 /// </summary> /// <param name="index"></param> /// <param name="item"></param> public void Insert(int index, GameObject item) { if (item == null) { return; } if (m_Instances.Contains(item)) { return; } RenameInstance(item); m_Instances.Insert(index, item); ReusableObject reusable = GetOrAddReusableObject(item); reusable.isFromPool = true; reusable.onDestroyed = ReusableObject_onDestroyed; reusable.onDespawn = ReusableObject_onDespawn; if (reparentOnCreated) { item.transform.SetParent(m_Pool.transform, false); } if (item.gameObject.activeSelf) { reusable.Spawn(); } else { m_RecycledInstances.Add(item); } }
/// <summary> /// 预创建Instance /// </summary> /// <param name="collection"></param> /// <returns></returns> private IEnumerator PreCreateInstance(InstanceCollection collection) { if (collection == null) { yield break; } if (m_EditorLog) { Debug.LogFormat( "{0} -> {1} -> Start pre-load instances. Count('{2}').", poolName, collection.prefabName, collection.preCount ); } yield return(null); while (collection.Count < collection.preCount) { int count = Mathf.Min(collection.preCount - collection.Count, collection.preCountPerFrame); for (int i = 0; i < count; i++) { GameObject go = GameObject.Instantiate(collection.prefab); ReusableObject reusable = GetOrAddReusableObject(go); reusable.Despawn(false); collection.Add(go); } yield return(null); } }
/// <summary> /// 获取未使用Instance,如果没有,则创建一个Instance /// </summary> /// <returns></returns> internal GameObject GetOrCreateRecycledInstance() { GameObject instance; if (recycledCount > 0) { instance = m_RecycledInstances[recycledCount - 1]; m_RecycledInstances.RemoveAt(recycledCount - 1); } else { instance = GameObject.Instantiate(prefab); RenameInstance(instance); m_Instances.Add(instance); ReusableObject reusable = GetOrAddReusableObject(instance); reusable.isFromPool = true; reusable.onDestroyed = ReusableObject_onDestroyed; reusable.onDespawn = ReusableObject_onDespawn; if (reparentOnCreated) { instance.transform.SetParent(m_Pool.transform, false); } } return(instance); }
private void ReusableObject_onDespawn(ReusableObject reusable) { m_RecycledInstances.Add(reusable.gameObject); if (reparentOnCreated && reusable.transform.parent != m_Pool.transform) { reusable.transform.SetParent(m_Pool.transform, false); } }
/// <summary> /// 获取或添加ReusableObject组件 /// </summary> /// <param name="instance"></param> /// <returns></returns> public static ReusableObject GetOrAddReusableObject(GameObject instance) { ReusableObject reusable = instance.GetComponent <ReusableObject>(); if (reusable == null) { reusable = instance.AddComponent <ReusableObject>(); } return(reusable); }
/// <summary> /// 移除出池子, /// 注意,如果它的父对象是DontDestroy,你需要手动销毁它或改变它的父对象让场景销毁它。 /// </summary> /// <param name="item"></param> /// <returns></returns> public bool Remove(GameObject item) { if (!m_Instances.Contains(item)) { return(false); } ReusableObject reusable = item.GetComponent <ReusableObject>(); reusable.isFromPool = false; m_RecycledInstances.Remove(item); return(m_Instances.Remove(item)); }
/// <summary> /// 回收一个Instance。 /// true:回收成功。 /// 有debug warning:参数instance为null,return false。 /// 有debug error:这个GameObject不是由Pool创建的,return false。 /// false:当没有error和warning时,instance是从其它pool里生成的,或者是没有添加到pool的外部instance。 /// </summary> /// <param name="instance"></param> /// <returns></returns> public bool Despawn(GameObject instance) { if (instance == null) { Debug.LogWarningFormat("{0} -> You tryed despawn a 'null' instance.", poolName); return(false); } ReusableObject reusable = instance.GetComponent <ReusableObject>(); if (reusable == null) { Debug.LogErrorFormat("{0} -> This GameObject is not a instance from pool."); return(false); } // 外部instance,没有加入任何pool if (!reusable.isFromPool) { return(false); } // 找到存在这个instance的collection InstanceCollection collection = m_InstanceCollections.Find(c => c.Contains(instance)); // 没有找到,说明是其它pool里生成的 if (collection == null) { return(false); } reusable.Despawn(true); if (m_EditorLog) { Debug.LogFormat( "{0} -> Despawn a instance named '{1}'.", poolName, instance.name ); } return(true); }
/// <summary> /// 释放集合,并销毁所有Instances /// </summary> public void Dispose() { if (m_Pool != null) { // 从Pool中移除此collection m_Pool.RemoveCollectionInternal(this); m_Pool = null; } m_Prefab = null; m_RecycledInstances = null; // Destroy所有instances for (int i = 0; i < m_Instances.Count; i++) { GameObject instance = m_Instances[i]; ReusableObject reusable = instance.GetComponent <ReusableObject>(); reusable.onDespawn = null; reusable.onDestroyed = null; GameObject.Destroy(instance); } m_Instances = null; }
private void ReusableObject_onDestroyed(ReusableObject reusable) { m_RecycledInstances.Remove(reusable.gameObject); m_Instances.Remove(reusable.gameObject); }