unity 对象池编写

来源:互联网 发布:默默是什么软件 编辑:程序博客网 时间:2024/05/18 02:22
   先聊聊对象池吧 ,说白了就是我们把经常实例化的东西经常实例 然后又删除。这应该是常人的操作吧。而对象池的作用就是把后面哪一部分放到一个list里面,把它设置成setactive(false)。当我们再实例的时候然后从list中取。总体来说很简单。
   首先我们假如要生成一个子弹,过会我们需要生产一个炮弹,对于这2中物体,我们应该生成2个池子 然后用一个总池子去管理这2个小池子了,这些应该很好理解吧,当然这个池子在任何时候都可以被调用,所以这个池子应该是个单例。我建议单例 最好去用单例组件那样去写。至于单例组件怎么写,我在下次 消息出来机制中给大家详细的讲。这里有不讲了。
  首先我们先看一下一个小池子的书写吧,我们定义这个类为objectpool。这个池子应该有最基本的3个方法吧 首先初始化吧。这让我们知道这个池子里面是回收什么的,是可以生成什么的。接下来就是实例化一个游戏物体方法,回收一个游戏物体。同时也应该有一些辅助方法。例如将池子销毁掉方法,说实在的话 不知道怎么和你们讲具体的代码 ,我还是贴代码。然后再代码中去讲解吧。
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;


public class ObjectPool
{
    public event Action<GameObject> OnSpawnedEvent;
    public event Action<GameObject> onDespawnedEvent;


    public GameObject Prefab;//注释这个池子里面的原始东西。这个物体时子弹的话 ,那么这个池子就只生成和销毁子弹了。
    public int InstancesToPreallocate = 5;//池子里面最多能有个数
    public int InstancesToAllocateIfEmpty = 1;//池子最少的个数

    public int HardLimit = 5;//最多限制个数
    public int InstancesToMaintainInPool = 5;
    public bool PersistBetweenScenes = false;


    private Stack<GameObject> _gameObjectPool;




    public void Initialize()//初始化池子
    {
        _gameObjectPool = new Stack<GameObject>(InstancesToPreallocate);
        AllocateGameObjects(InstancesToPreallocate);
    }


    public void ClearStack()//这里池子用的数据结构是栈  你也可以用链表,队列都行。这个方法是清空栈
    {
        if (_gameObjectPool.Count > InstancesToMaintainInPool)
        {
            for (int i = InstancesToMaintainInPool; i < _gameObjectPool.Count; i++)
            {
                Object.Destroy(_gameObjectPool.Pop());
            }
        }
    }


    public GameObject Spawn()//实例化一个游戏物体
    {


        var go = Pop();
        return go;
    }


    public void RecycleObj(GameObject ob)//回收一个游戏物体,将物体设置成不可见,然后放到栈中
    {
        ob.transform.parent = Pools.Instance.gameObject.transform;
        ob.SetActive(false);
        _gameObjectPool.Push(ob);
    }
    private GameObject Pop()
    {
        if (_gameObjectPool.Count > 0)
        {
            return _gameObjectPool.Pop();
        }
        AllocateGameObjects(InstancesToAllocateIfEmpty);
        return Pop();
    }


    public void ClearPool(bool shouldDestroyAllManagedObjects)//qing
    {
        while (_gameObjectPool.Count > 0)
        {
            var go = _gameObjectPool.Pop();
            if (shouldDestroyAllManagedObjects)
                Object.Destroy(go);
        }
    }
    private void AllocateGameObjects(int  count)
    {
        for (int n = 0; n < count; n++)
        {
            GameObject go = Object.Instantiate(Prefab.gameObject) as GameObject;
            go.name = Prefab.name;
            if (go.transform as RectTransform)
            {
                go.transform.SetParent(Pools.Instance.Transform, false);
                go.SetActive(false);
            }
            else
            {
                go.transform.parent = Pools.Instance.Transform;
                go.SetActive(false);
            }
            _gameObjectPool.Push(go);
        }
    }
 

}
当我们在看别人的代码结构的时候 一些私有方法是可以不用看的,当你要具体了解某个类的作用的时候,这是才开始看。当然接口是最需要看。这只是一种类型物体的池子。我们下节看一个主管理池子的大池子。
0 0