对象池实操(二)_对一的演示的补充_实现对象的数据重置

来源:互联网 发布:反ps软件叫什么 编辑:程序博客网 时间:2024/06/05 09:50

对象池实操(二)_对一的演示的补充_实现对象的数据重置<15/10/2017>

先看效果,主要是实现了一个重置的过程:


一共四个脚本,一个是池管理PoolManager,一个是测试管理TestManager,一个是池对象PoolObject,一个是测试对象TestObject:

PoolManager脚本:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class PoolManager : MonoBehaviour{    Dictionary<int, Queue<ObjectInstance>> poolDictionary = new Dictionary<int, Queue<ObjectInstance>>();//键名不存在顺序之分    static PoolManager _instance;    public static PoolManager instance    {        get        {            if (_instance == null)            {                _instance = FindObjectOfType<PoolManager>();//找到身上挂有PoolManager脚本的物体类型(单例模式)            }            return _instance;        }    }    public void CreatePool(GameObject prefab, int poolSize)    {        int poolKey = prefab.GetInstanceID();//***物体的实例id始终保证是独一无二的***        GameObject poolHolder = new GameObject(prefab.name + "pool");//把所有预制体同一进行管理,避免杂乱        poolHolder.transform.parent = transform;//把这个用来分类管理的空父物体的父类都定义为PoolManager,以至于不那么杂乱        if (!poolDictionary.ContainsKey(poolKey))//检查有没有唯一ID,没有就增加        {            poolDictionary.Add(poolKey, new Queue<ObjectInstance>());        }        for (int i = 0; i < poolSize; i++)//产生对应的对象后,不激活对象,且用队列的形式放到字典Dictionary中        {            ObjectInstance newObject = new ObjectInstance(Instantiate(prefab) as GameObject);            poolDictionary[poolKey].Enqueue(newObject);//入列存字典Dictionary中            newObject.SetParent(poolHolder.transform);        }    }    public void ReuseObject(GameObject prefab, Vector3 position, Quaternion rotation)    {        int poolKey = prefab.GetInstanceID();        if (poolDictionary.ContainsKey(poolKey))//对象的重用,先找有没有这个对象,找到后出列用新的引用指针调用,然后再入列,很有调用逻辑,每次都是按顺序使用        {            ObjectInstance objectToReuse = poolDictionary[poolKey].Dequeue();//创造一个空的对象来引用指向在字典中的它,踢出队列最前排            poolDictionary[poolKey].Enqueue(objectToReuse);//回到队列最后排            objectToReuse.Reuse(position, rotation);//调用类的方法来实现调用的方法        }    }    public class ObjectInstance//定义一个类来存储对象信息,使得其重置对象的所有数据参数,使得其每次调用都是全新的开始    {        GameObject gameObject;        Transform transform;        bool hasPoolObjectComponent;//判断对象是否拥有PoolObjecet组件(TestObject继承于PoolObject),然后进行判断        PoolObject poolObjectScript;        public ObjectInstance(GameObject objectInstance)//构造方法        {            gameObject = objectInstance;            transform = gameObject.transform;            gameObject.SetActive(false);//开始时默认都是不激活的状态            if (gameObject.GetComponent<PoolObject>())//TestObject继承于PoolObject,每个预制体身上都有个TestObject            {                hasPoolObjectComponent = true;                poolObjectScript = gameObject.GetComponent<PoolObject>();//复用重置            }        }        public void Reuse(Vector3 position, Quaternion rotation)        {            if (hasPoolObjectComponent)//用于重置对象属性的判断            {                poolObjectScript.OnObjectReuse();//TestObject等同于PoolObject            }            gameObject.SetActive(true);            transform.position = position;            transform.rotation = rotation;        }        public void SetParent(Transform parent)//归类管理,避免杂乱        {            transform.parent = parent;        }    }}
TestManager脚本:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class TestManager : MonoBehaviour{    public GameObject prefab;    void Start()    {        PoolManager.instance.CreatePool(prefab, 3);    }    void Update()    {        if (Input.GetKeyDown(KeyCode.Space))        {            PoolManager.instance.ReuseObject(prefab, Vector3.zero, Quaternion.identity);        }    }}

PoolObject脚本:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class PoolObject : MonoBehaviour{    public virtual void OnObjectReuse()    {    }    protected void OnDestroy()    {        gameObject.SetActive(false);//用false不激活设置代替该对象被删除    }}
TestObject脚本:(继承于PoolObject)

using System.Collections;using System.Collections.Generic;using UnityEngine;public class TestObject : PoolObject{    TrailRenderer trail;    float trailTime;    private void Awake()    {        trail = GetComponent<TrailRenderer>();//拿到自身的拖尾组件,好吧这个不重要可以忽略        trailTime = trail.time;    }    void Update()    {        transform.localScale += Vector3.one * Time.deltaTime;//预制体体积不断增大        transform.Translate(Vector3.left * Time.deltaTime * 5);//预制体诞生后持续朝一个方向移动    }    public override void OnObjectReuse()//每次使用复用对象时,都会重置对象的各类属性值,使得其复用回到初始状态,而不是调用变化后的效果    {        trail.time = -1;        Invoke("ResetTrail", .1f);//0.1秒后激活拖尾效果        transform.localScale = Vector3.one;//重置对象的体积    }    void ResetTrail()    {        trail.time = trailTime;    }}

运行前和运行时的层级视图:

运行前运行时

最终效果(主要是重置):





原创粉丝点击