Unity对象池的创建与使用


本文提供全流程,中文翻译。

Chinar 坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)



Chinar —— 心分享、心创新!

助力快速完成 Unity 对象池的创建与使用

为新手节省宝贵的时间,避免采坑!


Chinar 教程效果:



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

MonoSingleton —— 单例基类


任何继承自 MonoSingleton 泛型基类的脚本/类 都是单例类

举个栗子黑白88

using UnityEngine;/// <summary>/// 泛型单例基类 —— 任何继承自该类的类,都是单例类/// </summary>/// <typeparam name="T">泛型</typeparam>public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>{    private static T instance;    public static T Instance    {        get        {            if (instance == null)            {                instance = Find OfType(typeof(T)) as T;                if (instance == null) instance = new Game ("Chinar Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>();            }            return instance;        }    }    private void Awake()    {        if (instance == null) instance = this as T;    }    private void OnApplicationQuit()    {        instance = null;    }}

2

Pool —— 对象池


新建一个脚本 Pool 继承自泛型基类 MonoSingleton《 Pool》

是以 Pool 就会是一个单例类
举个栗子黑白88

using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 对象池(重复调用/使用的游戏物体)  子弹,技能,导弹,敌人/// </summary>public class  Pool : MonoSingleton< Pool>{    //字段  池 技能预设物(因为一个技能可能有多个预制件) 技能的复用性    private Dictionary<string, List<Game >> cache = new Dictionary<string, List<Game >>();    int                                          i     = 0; //标记 0    /// <summary>    /// 创建显示对象    /// </summary>    /// <returns>The  .</returns>    /// <param name="key">对象名称</param>    /// <param name="go">对象的预制件</param>    /// <param name="position">对象的新位置</param>    /// <param name="quaternion">对象的角度</param>    public Game  Create (string key, Game  go, Vector3 position, Quaternion quaternion)    {        Game  tempgo = cache.ContainsKey(key) ? cache[key].Find(p => !p.activeSelf) : null; //返回池中未激活的对象,所有都被激活就返回空,赋值给临时对象        if (tempgo != null)                                                                      //如果临时对象不为空        {            tempgo.transform.position = position;   //设置位置            tempgo.transform.rotation = quaternion; //旋转信息        }        else //否则,就是空了。(也就是没能从池子里取出对象)        {            tempgo = Instantiate(go, position, quaternion); //那就根据传入的预设物,生成一个新物体            print("实例化物体数量:" + i++);            if (!cache.ContainsKey(key)) //池中没有键            {                cache.Add(key, new List<Game >()); //新建一个 列表            }            cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了        }        tempgo.SetActive(true); //并启用临时物体        return tempgo;          //返回    }    /// <summary>    /// 直接回收    /// </summary>    /// <param name="go">Go.</param>    public void Collect (Game  go)    {        go.SetActive(false);    }    /// <summary>    /// 延迟回收    /// </summary>    /// <param name="go">Go.</param>    /// <param name="delay">Delay.</param>    public void Collect (Game  go, float delay)    {        StartCoroutine(Collect(go, delay));    }    private IEnumerator Collect(Game  go, float delay)    {        yield return new WaitForSeconds(delay);        Collect (go);    }    /// <summary>    /// 释放资源    /// </summary>    /// <returns>The clear.</returns>    /// <param name="key">Key.</param>    public void Clear(string key)    {        if (cache.ContainsKey(key))        {            //Destroy当中所有的对象            for (int i = 0; i < cache[key].Count; i++)            {                Destroy(cache[key][i]);            }            //清除键当中的所有值            //cache[key].Clear();            //清除这个键(键值一起清除)            cache.Remove(key);        }    }    /// <summary>    /// 释放所有对象池    /// </summary>    public void ClearAll()    {        var list = new List<string>(cache.Keys);        for (int i = 0; i < list.Count; i++)        {            Clear(list[i]);        }    }}

3

PoolTest —— 测试对象池的使用


新建一个脚本 PoolTest 用来测试对象池的使用
举个栗子黑白88

using UnityEngine;/// <summary>/// 测试对象池的调用/// </summary>public class PoolTest : MonoBehaviour{    Game  go;   //临时对象    Game  item; //临时对象池对象    void Start()    {        go = Resources.Load<Game >("Cube"); //在Resources文件目录下做一个Cube预设物    }    void Update()    {        if (Input.GetKey(KeyCode.Space)) //按下空格创建一个Cube        {            item                    =   Pool.Instance.Create (" 1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));            item.transform.position += new Vector3(0, 0, 1);        }        if (Input.GetMouseButtonDown(0)) //按下左键执行回收对象        {            if (item != null)            {                 Pool.Instance.Collect (item, 0.2f);            }        }        if (Input.GetMouseButtonDown(1)) //按下右键执行清除已经生成的对象        {             Pool.Instance.Clear(" 1");        }    }}

支持

May Be —— 搞开发,总有一天要做的事!


拥有自己的服务器,无需再找攻略!

Chinar 提供一站式教程,闭眼式创建!

为新手节省宝贵时间,避免采坑!


先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


1 —— 云服务器超全购买流程 (新手必备!)

2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)

3—— Windows 服务器配置、运行、建站一条龙 !

4 —— Linux 服务器配置、运行、建站一条龙 !



70

Chinar


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

收藏 打印