IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity对象池简单应用 -> 正文阅读

[游戏开发]Unity对象池简单应用

1.简单介绍

在Unity开发过程中,对象池是一种很好的能用于减少内存开销的方式。在许多场景中,比如角色射击出去的子弹,以及在游戏运行过程中频繁生成的敌人…如果在运行时实时在场景中Instance和Destory,在场景中需要实时生成的GameObject数量比较多的情况下,会增加内存的开销和影响游戏的性能。使用对象池可以很好的对这些需要实时刷新的游戏对象进行管理,在需要时从对象池中取(也就是SetActive(true)),不需要时回收到对象池中(也就是SetActive(false))。

2.思路

以下分了三个类来实现对象池的例子。
1.Pool(对象池类)
其中主要有获取对象GetObject()、回收对象ReleaseObject()、清空对象池ClearPool()三个方法。
2.PoolManager(对象池管理类)
用于管理所有的对象池,方法看代码有详细介绍
3.ObjectPoolTest(测试类)
用于测试对象池

代码实现

1.Pool

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

public class Pool
{
    int maxCount; //对象池存储数据的最大数据量
    public string prefabPath; //对象的存储路径
    List<GameObject> usingList = new List<GameObject>(); //正在使用中的对象
    List<GameObject> freeList = new List<GameObject>(0); //对象池中空闲的对象

    public Pool(int count)
    {
        this.maxCount = count;
    }

    /// <summary>
    /// 从对象池中获取对象
    /// </summary>
    /// <returns></returns>
    public GameObject GetObject()
    {
        GameObject obj = null;
        if(freeList.Count > 0) //如果有空闲列表不为空,从从空闲列表中取对象
        {
            obj = freeList[0];
            usingList.Add(obj); //取出的对象放入正在使用对象列表中
            freeList.RemoveAt(0); //从空闲列表中移除取出的对象
        }
        else //当不存在空闲列表时,则根据资源路径去实例化
        {
            if (usingList.Count >= maxCount) //如果当前场景中的对象已经达到对象池的最大上限,直接返回
                return obj;
            GameObject prefab = Resources.Load<GameObject>(prefabPath);
            obj = GameObject.Instantiate(prefab);
            //将实例化的新对象放入正在使用列表中
            usingList.Add(obj);
            int instanceID = obj.GetInstanceID();
            PoolManager.Instance.instanceIDToPathDic.Add(instanceID, prefabPath); //将克隆出来的对象ID和资源路径存如=入对象池管理类中
        }
        return obj;
    }

    /// <summary>
    /// 回收对象
    /// </summary>
    /// <param name="obj">需要回收的对象</param>
    public void ReleaseObject(GameObject obj)
    {
        usingList.Remove(obj);//将需要回收的对象从正在使用列表中移除
        freeList.Add(obj); //讲需要回收的对象加入到空闲列表中
    }
    /// <summary>
    /// 清空对象池
    /// </summary>
    public void ClearPool()
    {
        //销毁使用列表和空闲列表中的对象
        foreach (var item in usingList)
            GameObject.Destroy(item);
        foreach (var item in freeList)
            GameObject.Destroy(item);
        //清空列表
        usingList.Clear();
        freeList.Clear();
    }
}


2.PoolManager

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

public class PoolManager 
{
    static PoolManager instacne; //将对象池管理类设计成单例模式
    public static PoolManager Instance
    {
        get
        {
            if (instacne == null)
                instacne = new PoolManager();
            return instacne;
        }
    }

    public Dictionary<string, Pool> allPoolDic = new Dictionary<string, Pool>(); //存储了所有对象池
    public Dictionary<int, string> instanceIDToPathDic = new Dictionary<int, string>(); //存储了所有对象的实例化ID和该对象对应的对象池的资源路径
    /// <summary>
    /// 从相应的对象池中取得相应的对象
    /// </summary>
    /// <param name="prefabPath"></param>
    /// <returns></returns>
    public GameObject GetObjFormPoll(string prefabPath)
    {
        GameObject obj = null;
        if(allPoolDic.ContainsKey(prefabPath)) //先判断该资源对应的对象池是否存在
        {
            Pool pool = allPoolDic[prefabPath];
            obj = pool.GetObject();
        }
        else
        {
            //当前字典中不存在该对象池,则新创建对象池
            int maxCount = 5;
            Pool pool = new Pool(maxCount);
            pool.prefabPath = prefabPath;
            allPoolDic.Add(prefabPath, pool);
            obj = pool.GetObject();
        }
        //将对象设置成激活状态
        if (obj != null)
            obj.SetActive(true);
        return obj;
    }

    /// <summary>
    /// 将对象还回对象池中
    /// </summary>
    public void ReleaseObjToPool(GameObject obj)
    {
        if (obj == null)
            return;
        int instanceID = obj.GetInstanceID();
        if(instanceIDToPathDic.ContainsKey(instanceID))
        {
            string prefabPath = instanceIDToPathDic[instanceID]; //获取该对象对应的资源路径
            if(allPoolDic.ContainsKey(prefabPath))
            {
                Pool pool = allPoolDic[prefabPath];
                pool.ReleaseObject(obj);
                obj.SetActive(false); //回收后将对象设置为隐藏状态
            }
        }
    }
    /// <summary>
    /// 清空对象池
    /// </summary>
    public void ClearAllPool()
    {
        foreach (var item in allPoolDic.Values)
            item.ClearPool(); //清空每个对象池
        allPoolDic.Clear();
        instanceIDToPathDic.Clear();
    }
}

3.ObjectPoolTest

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

public class ObjectPoolTest : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        //从对象池中创建对象
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Vector3 pos = new Vector3(Random.Range(-5, 5), Random.Range(-5, 5), Random.Range(-5, 5));
            GameObject obj = PoolManager.Instance.GetObjFormPoll("Cube");
            obj.transform.position = pos;
        }
        //回收从对象池创建的对象
        if(Input.GetKeyDown(KeyCode.R))
        {
            GameObject obj = GameObject.Find("Cube(Clone)");
            PoolManager.Instance.ReleaseObjToPool(obj);
        }
    }
}

4.测试结果

在这里插入图片描述
可以看到,无论我们按几次空格键,场景中最多只会生成5个对象,因为限制了对象池最大数量为5,当你不需要使用时,就按R把对象隐藏起来,而不是直接删除掉。下次需要用到对象的时候直接将状态设置为显示,而不是重新实例化。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 16:17:43  更:2021-12-14 16:18:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:05:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码