欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity 对象池

程序员文章站 2022-07-13 15:17:59
...

一、为什么使用对象池

1、如果不使用对象池会怎么样?假设FPS游戏按下鼠标左键发射子弹,然后子弹到达相应的位置删除对象。如果突然场景中出现了1000个人每人发射30颗子弹,可能会造成卡死等,具体什么现象没验证过。最主要的是会触发.Net的GC(垃圾回收机制),当触发了垃圾回收程序会卡。
2、对象池的优点:不用一直创建对象,把经常重发创建删除的对象全部储存在对象池中,如果使用直接从对象池中拿出,用完放回去,减少CPU负担。
3、对象池的缺点:减少CPU负担增加内存容量。增加的容量可以忽略不记。

二、对象池设计思路

Unity 对象池

三、对象池代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameObjectPool : MonoSingleton<GameObjectPool> {
	//对象池
    private Dictionary<string, List<GameObject>> pool;


    //初始化
    public override void Initialize()
    {
        base.Initialize();
        pool = new Dictionary<string, List<GameObject>>();
    }
    //代码思路是:创建对象时判断池中是否有对象如果没有那么创建,如果有判断是否可见如果不可见那么创建添加进池中
    /// <summary>
    /// 通过对象池创建对象
    /// </summary>
    /// <param name="key">key</param>
    /// <param name="prefabGameObjec">预制件</param>
    /// <param name="pos">位置</param>
    /// <param name="rot">旋转</param>
    /// <returns></returns>
    public GameObject CreateGameObject(string key, GameObject prefabGameObjec, Vector3 pos, Quaternion rot)
    {
        GameObject tempGo = null;

        //判断对象池中是否存在和能否使用
        if (pool.ContainsKey(key))
            tempGo = pool[key].Find(go => !go.activeInHierarchy);


        //对象池没有key或者对象池中的对象不可用
        if (tempGo == null)
        {
            //创建游戏对象
            tempGo = GameObject.Instantiate(prefabGameObjec, pos, rot);
            //如果key不存在创建列表
            if (!pool.ContainsKey(key)) pool.Add(key, new List<GameObject>());
            //添加进入对象池列表
            pool[key].Add(tempGo);
        }

        //设置位置
        tempGo.SetActive(true);
        tempGo.transform.position = pos;
        tempGo.transform.rotation = rot;
        return tempGo;
    }

    /// <summary>
    /// 回收对象
    /// </summary>
    /// <param name="go">游戏物体</param>
    /// <param name="delayed">延迟时间</param>
    public void RecycleGameObject(GameObject go,float delayed=0)
    {
        StartCoroutine(IeGameObjectDelayedHid(go,delayed));
    }

    private IEnumerator IeGameObjectDelayedHid(GameObject go, float delayed)
    {
        yield return new WaitForSeconds(delayed);
        go.SetActive(false);
    }
}