Example #1
0
    private void OnEnable()
    {
        markerPoolParent = transform.Find(markerPoolParentName);
        markerPool       = new TransformPool(markerPoolParent);

        playerWorldPositionPath.Subscribe(State.Instance.Player.WorldPositionPath, HandlePlayerWorldPositionPathChange);
    }
Example #2
0
        /// <summary>
        /// Returns a pool that is appropriate for storing identical copies of an object.
        /// </summary>
        static TransformPool GetAssociatedPool(GameObject gameObject, int chunkSize, int maxPoolSize)
        {
            //first, we need to know the id we will be using for this object's pool
            //if there is no PoolId attached we know this wasn't created by this pooler.
            //In that case, treat is as a prefab. WARNING: If it isn't actually a prefab and we
            //destroy it later, this could cause some serious issues!
            PoolId p  = null;
            int    id = PoolIdValue(gameObject, out p);

            //now we need to see if we have a pool for it yet
            TransformPool pool = null;

            if (!Pools.TryGetValue(id, out pool))
            {
                //looks like we need to create a new pool for this type of object
                GameObject go = new GameObject("Pool: " + id + " (" + gameObject.name + ")");
                go.transform.SetParent(Instance.transform, false);
                pool             = go.AddComponent <TransformPool>();
                pool.PoolId      = id;
                Pools[id]        = pool;
                pool.ChunkSize   = chunkSize;
                pool.MaxPoolSize = maxPoolSize;
                pool.AllocTime   = AllocTime;

                //WARNING: This is a potential bug if we actually passed a live object and not a prefab!
                //If we destroy the live object, we can't properly use the pool associated with it!
                pool.Prefab = gameObject.transform;
            }

            return(pool);
        }
Example #3
0
    private void OnEnable()
    {
        markerPoolParent = transform.Find(markerPoolParentName);
        markerPool       = new TransformPool(markerPoolParent);

        inputWorldPositions.Subscribe(State.Instance.Input.WorldPositions, HandleInputWorldPositionsChange);
    }
Example #4
0
        /// <summary>
        /// 分批预加载实例(细节执行)。
        /// </summary>
        /// <param name="poolName">对象池名称。</param>
        /// <param name="prefab">Prefab。</param>
        /// <param name="amount">创建的实例总数量。</param>
        /// <param name="perAmount">每帧创建的实例数量,为 0 是一次性创建全部。</param>
        private void DoPreload(string poolName, Transform prefab, int amount, int perAmount)
        {
            PrefabPool    prefabPool    = GetPrefabPool(prefab);
            TransformPool transformPool = GetTransformPool(poolName);
            bool          prefabEnabled = prefab.gameObject.activeSelf;

            prefab.gameObject.SetActive(false);
            perAmount = perAmount <= 0 ? amount : perAmount;
            StartPreloading(prefabPool, prefabEnabled, transformPool, amount, perAmount);
        }
Example #5
0
        /// <summary>
        /// 创建一个新的物体并挂接一个 PoolEntity 组件。
        /// </summary>
        /// <param name="prefabPool">Prefab 对象池。</param>
        /// <param name="transformPool">Transform 对象池。</param>
        /// <param name="enable">是否激活。</param>
        /// <param name="position">创建后的初始位置。</param>
        /// <param name="rotation">创建后的初始方向。</param>
        /// <returns>创建出来的实例。</returns>
        private static Transform Instantiate(PrefabPool prefabPool,
                                             TransformPool transformPool,
                                             bool enable,
                                             out PoolEntity comp,
                                             Vector3 position    = default(Vector3),
                                             Quaternion rotation = default(Quaternion))
        {
            if (count >= Instance.maxCount)
            {
                throw new ApplicationException(
                          "POOL MANAGER: \nThe number of game objects has reached its limit! Try to increase the Max Count of PoolManager.");
            }

            // 创建新的实例
            Transform xform;

            xform             = Instantiate(prefabPool.Prefab, position, rotation) as Transform;
            prefabPool.Count += 1;
            xform.name       += prefabPool.Count.ToString("#000");

            // 添加 PoolEntity/PoolParticle 组件

            ParticleSystem ps = xform.GetComponent <ParticleSystem>();

            comp = ps
                       ? xform.gameObject.AddComponent <PoolParticle>()
                       : xform.gameObject.AddComponent <PoolEntity>();

            comp.PrefabPool    = prefabPool;
            comp.Prefab        = prefabPool.Prefab;
            comp.Index         = count;
            comp.OriginalScale = xform.localScale;

            // 添加到大数组
            allTransforms[count]   = xform;
            allPoolEntities[count] = comp;
            count += 1;

            // 添加到 prefab 对象池
            if (enable)
            {
                comp.IsDespawned = false;
            }
            else
            {
                prefabPool.DisabledPool.Push(comp.Index);
            }

            // 添加到 Transform 对象池
            // need comp.Index
            AddToTransformPool(xform, comp, transformPool, enable);

            return(xform);
        }
Example #6
0
        /// <summary>
        /// Relenquishes an object to the internal pooling mechanism. For all intents
        /// and purposes, this should be treated the same as calling Destroy on the GameObject
        /// and it should no longer be accessed. If the internal pool is at maximum capacity
        /// the GameObject will be destroyed.
        ///
        /// Note that even if an object was not instantiated using a pool, it can still be
        /// relenquished to one, however, the pool it is placed in will not be the same one
        /// as any other copies that were instantiated using Summon().
        /// </summary>
        /// <param name="gameObject"></param>
        public static void RelenquishToPool(GameObject gameObject)
        {
            if (gameObject == null)
            {
                return;
            }

            //don't use pools during editmode, it f***s everything // lol
            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                //var prefabType = UnityEditor.PrefabUtility.GetPrefabType(gameObject);
                var prefabType   = UnityEditor.PrefabUtility.GetPrefabAssetType(gameObject);
                var prefabStatus = UnityEditor.PrefabUtility.GetPrefabInstanceStatus(gameObject);

                //if (prefabType == UnityEditor.PrefabType.None || (int)prefabType >= (int)UnityEditor.PrefabType.PrefabInstance)
                if (prefabType == UnityEditor.PrefabAssetType.NotAPrefab && prefabStatus == UnityEditor.PrefabInstanceStatus.NotAPrefab ||
                    (int)prefabStatus >= (int)UnityEditor.PrefabInstanceStatus.Disconnected)
                {
                    DestroyImmediate(gameObject);
                }
                else
                {
                    Debug.LogWarning("Could not destroy prefab: " + gameObject.name);
                }
                return;
            }
            #endif

            if (MaxPoolSize < 1)
            {
                Destroy(gameObject);
                return;
            }

            //If we don't have a pool for this object's id
            //we know it didn't come from one. We just want
            //to destroy it like normal.
            int id = PoolIdValue(gameObject);

            TransformPool pool = null;
            if (Pools.TryGetValue(id, out pool))
            {
                pool.RelenquishObject(gameObject.transform);
            }
            else
            {
                Destroy(gameObject);
            }
        }
Example #7
0
        /// <summary>
        /// 创建 Transform 对象池。
        /// </summary>
        /// <param name="name">对象池名称。</param>
        /// <returns>TransformPool 对象。</returns>
        private static TransformPool CreateTransformPool(string name)
        {
            if (!root)
            {
                CreateRoot();
            }

            TransformPool pool = new TransformPool();

            pool.PoolName = name;
            pool.Group    = (new GameObject(name)).transform;
            pool.Group.SetParent(root);
            transformPoolDic.Add(name, pool);
            return(pool);
        }
Example #8
0
        /// <summary>
        /// This forces all entities that came from the specified pool to immediately
        /// relenquish back to it. Note that this may cause some entities
        /// to become destroyed if the pool is at full capcity.
        /// </summary>
        /// <param name="poolId"></param>
        public static void RelenquishPool(TransformPool pool)
        {
            //there are no pooled resources when in edit mode
            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                return;
            }
            #endif

            //if there is no instance, there can't possibly be any pools
            if (pool != null && Instance != null)
            {
                pool.RecallAll();                                   //BUG ALERT: not setting PoolId.InPool!
            }
        }
Example #9
0
        // ------------------------------------------------------
        // Spawn
        // ------------------------------------------------------

        /// <summary>
        /// 将一个物体加入对象池。
        /// </summary>
        /// <param name="xform">物体实例。</param>
        /// <param name="comp">物体实例上的 PoolEntity 组件。</param>
        /// <param name="pool">对象池 Transform。</param>
        /// <param name="enable">物体是否活跃。</param>
        private static void AddToTransformPool(Transform xform, PoolEntity comp, TransformPool pool, bool enable)
        {
            if (enable)
            {
                pool.EnabledPool.Add(comp.Index);
            }
            else
            {
                pool.DisabledPool.Add(comp.Index);
            }

            comp.TransformPool = pool;
            comp.Group         = pool.Group;
            comp.PoolName      = pool.PoolName;
            xform.SetParent(pool.Group);
        }
Example #10
0
        /// <summary>
        /// 回收一个实例。
        /// </summary>
        /// <param name="index">实例在大数组中的索引。</param>
        /// <param name="reparent">是否重新挂接到所属的对象池节点。</param>
        /// <exception cref="ApplicationException">实例早已被回收。</exception>
        public static void Despawn(int index, bool reparent = true)
        {
            PoolEntity comp = allPoolEntities[index];

            if (!comp)
            {
#if !UNITY_EDITOR
                Debug.Log("It seems that the whole object pool has been destroyed.");
#endif
                return;
            }

            TransformPool transformPool = transformPoolDic[comp.PoolName];
            PrefabPool    prefabPool    = prefabPoolDic[comp.Prefab];

            if (comp.IsDespawned)
            {
                throw new ApplicationException(string.Format(
                                                   "Game object seems to be despawned already: {0}",
                                                   GetByIndex(index).name));
            }

            prefabPool.DisabledPool.Push(index);
            transformPool.EnabledPool.Remove(index);
            transformPool.DisabledPool.Add(index);

            // 1. 调用所有 PoolBehaviour 组件的 OnDespawn() 方法
            // 2. 特定类型的 PoolEntity 有时候需要在 Despawn 时执行一些特定的工作,如 PoolParticle 清除粒子等
            comp.OnDespawn();
            comp.gameObject.SetActive(false);

            if (reparent)
            {
                allTransforms[index].SetParent(comp.Group);
            }

            if (comp.OnDespawnedCallback != null)
            {
                comp.OnDespawnedCallback();
                comp.OnDespawnedCallback = null;
            }

            comp.IsDespawned = true;
        }
Example #11
0
        /// <summary>
        /// 分批加载实例协程。
        /// </summary>
        /// <param name="prefabPool">Prefab 对象池。</param>
        /// <param name="prefabEnabled">Prefab 对象池活跃实例集合。</param>
        /// <param name="transformPool">Transform 对象池。</param>
        /// <param name="amount">创建的实例总数量。</param>
        /// <param name="perAmount">每帧创建的实例数量,为 0 时一次性创建全部。</param>
        /// <returns>IEnumerator 对象。</returns>
        internal IEnumerator PreloadBatch(PrefabPool prefabPool, bool prefabEnabled,
                                          TransformPool transformPool, int amount, int perAmount)
        {
            yield return(new WaitForEndOfFrame());

            PoolEntity comp;

            for (int i = 0; i < perAmount; i++)
            {
                Instantiate(prefabPool, transformPool, false, out comp);
                amount -= 1;

                if (amount == 0)
                {
                    prefabPool.Prefab.gameObject.SetActive(prefabEnabled);
                    yield break;
                }
            }

            StartCoroutine(PreloadBatch(prefabPool, prefabEnabled, transformPool, amount, perAmount));
        }
Example #12
0
 /// <summary>
 /// 开始执行分批加载实例。
 /// </summary>
 /// <param name="prefabPool">Prefab 对象池。</param>
 /// <param name="prefabEnabled">Prefab 对象池活跃实例集合。</param>
 /// <param name="transformPool">Transform 对象池。</param>
 /// <param name="amount">创建的实例总数量。</param>
 /// <param name="perAmount">每帧创建的实例数量,为 0 时一次性创建全部。</param>
 internal void StartPreloading(PrefabPool prefabPool, bool prefabEnabled,
                               TransformPool transformPool, int amount, int perAmount)
 {
     StartCoroutine(PreloadBatch(prefabPool, prefabEnabled, transformPool, amount, perAmount));
 }