推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

Unity零基础到进阶 ☀️| Unity中的对象池技术 ObjectPool

   2023-08-27 网络整理佚名1330
核心提示:对象池是一种Unity经常用到的内存管理服务,针对需要经常生成消失的对象,作用在于可以减少创建每个对象的系统开销。使用对象池的原因由于对象池中的对象只是(false)了,并非真正销毁了,所以一般运用于游戏中经常用到或需大量生成的物体。创建并使用一个简单对象池用于简单的使用对象池技术

对象池一、对象池的简单定义

对象池是Unity经常使用的内存管理服务。 对于需要频繁生成和消失的对象,可以减少创建每个对象的系统开销。 当对象需要消失时,我们不(false),然后将其放入池中(Queue)。 当我们需要再次显示一个新的对象时,我们首先去池中查看是否有隐藏的对象,然后将其取出(true),如果池中没有可用的,则再次显示。

2、使用对象池的原因

在Unity游戏开发过程中,经常会创建一些新的对象。 如果数量少,也是可以接受的。 如果新创建的对象数量较多,对内存来说将会是一个很大的隐患。 例如,在射击游戏中,每发射一颗子弹,都必须创建一个新的子弹对象,而且子弹数量巨大。 可想而知,一个游戏中会创建多少个这样的新物体,那么如果创建这些子弹的话。 游戏发挥关键且持续的作用是可以理解的。 问题是,子弹发射后,几秒钟后就不再有任何意义了。 一般会自动隐藏,也就是我们所说的(假),所以游戏场景中会出现很多不活动的物体。

由于对象池中的对象只是(假)并没有真正销毁,所以一般用于游戏中经常使用或者需要大量生成的对象。 并不是所有的物体都能使用这项技术,否则得不偿失。

3.创建并使用简单的对象池

首先我们生成一个对象池类,里面的内容很简单。 首先池中有一个Queue,用来存储对象,然后实现两个方法,一个用于取出对象,一个用于放入对象。 取对象时,如果池中有可用对象,则取出一个,如果没有,则取出一个; 当对象被放入时,该对象(false)将被放入池中。下图是一个简单的效果

首先有一个.cs,用于将其他脚本写入单例模式

namespace Utilty
{
    public class Singleton
    {
        private static T instance;
        public static T GetInstance()
        {
            if (instance == null)
            {
                instance = (T)Activator.CreateInstance(typeof(T), true);
            }
            return instance;
        }
    }
}
复制代码

.cs 用于加载和生成游戏对象

using System.Collections.Generic;
using UnityEngine;
//通用框架
namespace Utilty
{
    public class AssetsManager : Singleton
    {
        protected AssetsManager()
        {
            assetsCache = new Dictionary();
        }
        //缓存字典
        private Dictionary assetsCache;
        //获取资源
        public virtual T GetAssets(string path) where T : Object
        {
            //先查看缓存池中有没有这个资源
            if (assetsCache.ContainsKey(path))
            {
                //直接将这个资源返回
                return assetsCache[path] as T;
            }
            else
            {
                //通过Resource.Load去加载资源
                T assets = Resources.Load(path);
                //将新资源加载到缓存池里
                assetsCache.Add(path,assets);
                //返回资源
                return assets;
            }
        }
        //卸载未使用的资源
        public void UnloadUnusedAssets()
        {
            //卸载
            Resources.UnloadUnusedAssets();
        }
    }
    //加载图片
    public class SpriteManager : Singleton
    {
    }
    public class PrefabManager : Singleton
    {
        private PrefabManager() { }
        public GameObject CreateGameObjectByPrefab(string path)
        {
            //获取预设体
            GameObject prefab = AssetsManager.GetInstance().GetAssets(path);
            //生成
            GameObject obj = Object.Instantiate(prefab);
            // 返回
           return obj;
        }
        public GameObject CreateGameObjectByPrefab(string path, Vector3 pos, Quaternion qua)
        {
            //生成对象
            GameObject obj = CreateGameObjectByPrefab(path);
            //设置坐标和旋转
            obj.transform.position = pos;
            obj.transform.rotation = qua;
            //返回
            return obj;
        }
        public GameObject CreateGameObjectByPrefab(string path, Transform parent, Vector3 localPos, Quaternion localQua)
        {
            //生成对象
            GameObject obj = CreateGameObjectByPrefab(path);
            //设置父物体
            obj.transform.SetParent(parent);
            //设置坐标和旋转
            obj.transform.localPosition = localPos;
            obj.transform.localRotation = localQua;
            //返回
            return obj;
        }
    }
}
复制代码

.cs用于通过对象池生成并回收游戏对象

using System.Collections.Generic;
using UnityEngine;
namespace Utilty
{
   public class ObjectPool : Singleton
{
    //私有构造
    private ObjectPool()
    {
        pool = new Dictionary>();
    }
    //对象池
    private Dictionary> pool;
    //通过对象池生成游戏对象
    public GameObject SpawnObject(string name)
    {
        GameObject needObj;
        //查看是否有该名字所对应的子池,且子池中有对象
        if (pool.ContainsKey(name) && pool[name].Count > 0)
        {
            //将0号对象返回
            needObj = pool[name][0];
            //将0号对象从List中移除
            pool[name].RemoveAt(0);
        }
        else
        {
            //直接通过Instantiate生成
            needObj = PrefabManager.GetInstance().CreateGameObjectByPrefab(name);
            //修改名称(去掉Clone)
            needObj.name = name;
        }
        //设置为激活
        needObj.SetActive(true);
        //返回
        return needObj;
    }
        /// 
        /// 回收游戏对象到对象池
        /// 
        /// 
        public void RecycleObj(GameObject Objname)
    {
            //防止被看到,设置为非激活哦
            Objname.SetActive(false);
            if (pool.ContainsKey(Objname.name))
            {
                //将当前对象放入对象子池
                pool[Objname.name].Add(Objname);
            }
            else
            {
                //创建该子池并将对象放入
                pool.Add(Objname.name, new List { Objname });
         }
    }
}
}
复制代码

.cs 用于延迟收集对象

using System.Collections;
using UnityEngine;
using Utilty;
public class PoolObject : MonoBehaviour
{
    private void onEnable()
    {
        StartCoroutine(DelayRececle(2));
    }
    //延迟回收协程
    IEnumerator DelayRececle(float interval)
    {
        //等待几秒
        yield return new WaitForSeconds(interval);
        //回收当前对象
        ObjectPool.GetInstance().RecycleObj(gameObject);
    }
}
复制代码

Demo.cs用于对象池技术的简单使用

using UnityEngine;
using Utilty;
public class Demo : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.J))
        {
            GameObject go = ObjectPool.GetInstance().SpawnObject("Prefab");
            go.transform.position = Vector3.zero;
            go.transform.rotation = Quaternion.identity;
            go.GetComponent().velocity = Vector3.zero;
        }
    }
}

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON