unity中实现简单对象池,附教程原理

简介: Unity对象池的创建与使用本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar —— ...

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 = FindObjectOfType(typeof(T)) as T;
                if (instance == null) instance = new GameObject("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

ObjectPool —— 对象池


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

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

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


/// <summary>
/// 对象池(重复调用/使用的游戏物体)  子弹,技能,导弹,敌人
/// </summary>
public class ObjectPool : MonoSingleton<ObjectPool>
{
    //字段  池 技能预设物(因为一个技能可能有多个预制件) 技能的复用性
    private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>();
    int                                          i     = 0; //标记 0


    /// <summary>
    /// 创建显示对象
    /// </summary>
    /// <returns>The object.</returns>
    /// <param name="key">对象名称</param>
    /// <param name="go">对象的预制件</param>
    /// <param name="position">对象的新位置</param>
    /// <param name="quaternion">对象的角度</param>
    public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion)
    {
        GameObject 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<GameObject>()); //新建一个 列表
            }

            cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了
        }

        tempgo.SetActive(true); //并启用临时物体
        return tempgo;          //返回
    }


    /// <summary>
    /// 直接回收
    /// </summary>
    /// <param name="go">Go.</param>
    public void CollectObject(GameObject go)
    {
        go.SetActive(false);
    }


    /// <summary>
    /// 延迟回收
    /// </summary>
    /// <param name="go">Go.</param>
    /// <param name="delay">Delay.</param>
    public void CollectObject(GameObject go, float delay)
    {
        StartCoroutine(Collect(go, delay));
    }


    private IEnumerator Collect(GameObject go, float delay)
    {
        yield return new WaitForSeconds(delay);
        CollectObject(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
{
    GameObject go;   //临时对象
    GameObject item; //临时对象池对象


    void Start()
    {
        go = Resources.Load<GameObject>("Cube"); //在Resources文件目录下做一个Cube预设物
    }


    void Update()
    {
        if (Input.GetKey(KeyCode.Space)) //按下空格创建一个Cube
        {
            item                    =  ObjectPool.Instance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));
            item.transform.position += new Vector3(0, 0, 1);
        }


        if (Input.GetMouseButtonDown(0)) //按下左键执行回收对象
        {
            if (item != null)
            {
                ObjectPool.Instance.CollectObject(item, 0.2f);
            }
        }


        if (Input.GetMouseButtonDown(1)) //按下右键执行清除已经生成的对象
        {
            ObjectPool.Instance.Clear("Object1");
        }
    }
}

支持

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


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

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

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


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


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

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

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

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





Chinar


END

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

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

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

相关文章
|
4月前
|
存储 设计模式 监控
运用Unity Profiler定位内存泄漏并实施对象池管理优化内存使用
【7月更文第10天】在Unity游戏开发中,内存管理是至关重要的一个环节。内存泄漏不仅会导致游戏运行缓慢、卡顿,严重时甚至会引发崩溃。Unity Profiler作为一个强大的性能分析工具,能够帮助开发者深入理解应用程序的内存使用情况,从而定位并解决内存泄漏问题。同时,通过实施对象池管理策略,可以显著优化内存使用,提高游戏性能。本文将结合代码示例,详细介绍如何利用Unity Profiler定位内存泄漏,并实施对象池来优化内存使用。
293 0
|
3月前
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
159 3
|
3月前
|
图形学 数据可视化 开发者
超实用Unity Shader Graph教程:从零开始打造令人惊叹的游戏视觉特效,让你的作品瞬间高大上,附带示例代码与详细步骤解析!
【8月更文挑战第31天】Unity Shader Graph 是 Unity 引擎中的强大工具,通过可视化编程帮助开发者轻松创建复杂且炫酷的视觉效果。本文将指导你使用 Shader Graph 实现三种效果:彩虹色渐变着色器、动态光效和水波纹效果。首先确保安装最新版 Unity 并启用 Shader Graph。创建新材质和着色器图谱后,利用节点库中的预定义节点,在编辑区连接节点定义着色器行为。
262 0
|
3月前
|
API 图形学
Unity精华☀️Audio Mixer终极教程:用《双人成行》讲解它的用途
Unity精华☀️Audio Mixer终极教程:用《双人成行》讲解它的用途
|
3月前
|
图形学
Unity精华☀️点乘、叉乘终极教程:用《小小梦魇》讲解这个面试题~
Unity精华☀️点乘、叉乘终极教程:用《小小梦魇》讲解这个面试题~
|
3月前
|
图形学 数据安全/隐私保护 iOS开发
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
|
3月前
|
Apache 图形学
WebGL☀️Unity WebGL适配到各平台的教程
WebGL☀️Unity WebGL适配到各平台的教程
|
3月前
|
开发工具 图形学 Android开发
Pico Neo 3教程☀️ 二、从 PicoVR Unity SDK 迁移至 Unity XR SDK
Pico Neo 3教程☀️ 二、从 PicoVR Unity SDK 迁移至 Unity XR SDK
|
5月前
|
图形学
【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例(下)
【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例
117 0
|
5月前
|
数据可视化 图形学 开发者
【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例(上)
【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例
532 1