初探对象池

首先创建如下四个脚本
在这里插入图片描述
之后在场景中创建两个空节点:
一个挂载PoolManager作为对象池管理器。
一个挂载TestManager作为对象创建的位置。
在这里插入图片描述
之后在场景中创建一个Cube挂载TestObject作为对象池的子对象。

代码:

using UnityEngine;

/// <summary>
/// 创建出来的对象的父类
/// </summary>
public class PoolObject : MonoBehaviour
{
    public virtual void OnObjectReuse() { }

    protected void Destroy()
    {
        gameObject.SetActive(false);
    }
}
using UnityEngine;

public class PoolManager : MonoBehaviour
{
    Dictionary<int, Queue<ObjectInstance>> poolDictionary = new Dictionary<int, Queue<ObjectInstance>>();

    #region 单例
    private static PoolManager _instance;
    public static PoolManager instance
    {
        get 
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<PoolManager>();
            }
            return _instance;
        }
    }
    private void Awake()
    {
        //防止有多个单例
        if (_instance == null)
            _instance = this;
        else
            Destroy(gameObject);
    }
    #endregion

    public void CreatePool(GameObject prefab, int poolSize)//创建对象池的函数
    {
        /// <summary>
        ///同一个Prefab,不管是Inspector挂上去的还是用Resource.Load()动态加载的,这个ID都是一样的。
        ///只有当Instantiate成对象之后,每个对象间的ID才会有区别。
        ///不同的Prefab,ID是不一样的。
        /// </summary>
        int poolKey = prefab.GetInstanceID();//获取游戏对象的唯一ID标识

        //创建预制体并修改基础信息
        GameObject poolHolder = new GameObject(prefab.name + "_pool");
        poolHolder.transform.parent = transform;


        if (!poolDictionary.ContainsKey(poolKey))
        {
            poolDictionary.Add(poolKey, new Queue<ObjectInstance>());

            for (int i = 0; i < poolSize; i++)
            {
                //gon = newGameObject
                ObjectInstance gon = new ObjectInstance(Instantiate(prefab) as GameObject);
                poolDictionary[poolKey].Enqueue(gon);
                gon.SetParent(poolHolder.transform);
            }
        }
    }

    public void ReuseObject(GameObject prefab, Vector3 position, Quaternion rotation)//对象的重用函数
    {
        int poolKey = prefab.GetInstanceID();
        if (poolDictionary.ContainsKey(poolKey))
        {
            //gor = reuseGameObject
            ObjectInstance gor = poolDictionary[poolKey].Dequeue();//将队列头部弹出
            poolDictionary[poolKey].Enqueue(gor);//将弹出的内容重新压进队列作为队尾

            gor.Reuse(position,rotation);
        }
    }

    public class ObjectInstance
    {
        GameObject gameObject;
        Transform transform;

        bool hasPoolObjectComponent;
        PoolObject poolObjectScript;

        //构造函数,创建对象池中的子对象进行初始化使用
        public ObjectInstance(GameObject objectInstance)
        {
            gameObject = objectInstance;
            transform = gameObject.transform;
            gameObject.SetActive(false);
            if (gameObject.GetComponent<PoolObject>())
            {
                hasPoolObjectComponent = true;
                poolObjectScript = gameObject.GetComponent<PoolObject>();
            }
            else
            {
                Debug.LogError("无对象类");
            }
        }

        public void Reuse(Vector3 position, Quaternion rotation)
        {
            if (hasPoolObjectComponent)
            {
                poolObjectScript.OnObjectReuse();
            }

            gameObject.SetActive(true);
            transform.position = position;
            transform.rotation = rotation;
        }

        public void SetParent(Transform parent)
        {
            transform.parent = parent;
        }
    }
}
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.forward * Time.deltaTime * 25);
    }
    public override void OnObjectReuse()
    {
        //base.OnObjectReuse();
        trail.time = -1;
        Invoke("ResetTrail",0.1f);
        Invoke("Destroy", 5.0f);
        transform.localScale = Vector3.one;
    }
    private void ResetTrail()
    {
        trail.time = trailTime;
    }
}
using UnityEngine;

public class TestManager : MonoBehaviour
{
    public GameObject prefab;

    private void Start()
    {
        //创建对象池
        PoolManager.instance.CreatePool(prefab, 30);
    }

    // Update is called once per frame
    void Update()
    {
        //调用对象池中的对象
        if (Input.GetKeyDown(KeyCode.Space))
        {
            PoolManager.instance.ReuseObject(prefab,Vector3.zero,Quaternion.identity);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值