unity学习笔记#2--unity对象池
来源:互联网 发布:网页版淘宝的微淘 编辑:程序博客网 时间:2024/06/07 20:21
最近在看教程,学到了一点关于unity对象池的技术,现在来总结一下。
1.适用范围
在游戏中,总会有一些对象会重复出现在游戏场景中,比如敌人、子弹、特效……这些对象如果用一般的生成(Instantiate)及销毁(Destroy)方法来使其出现或消失在游戏场景中时,往往会造成很大的性能开销,尤其是在移动设备,如果大量使用此方法来处理对象的话会使得游戏变卡顿,影响游戏体验。因此可以用对象池技术来解决这个问题。
2.关于对象池
对象池就是将要重复出现在游戏场景中的物体(即可复用对象)在进入游戏场景中时预先生成,将其设置为未激活状态(设置SetActive属性为false,防止其在场景中出现)并存放在对象池中,当要让该物体出现在场景中时,将该物体从对象池中取出,激活并移动至指定地方。而当要让该物体消失于场景中时,则将其放入对象池中,并将其各项数值重置为默认(一些粒子对象是在播放完特效才消失的,便需要将其重置到播放前的状态),再设置其为未激活状态,需要注意的是,每个对象池里存储的可复用物体不能太多。
3.实现思路
以下为我参照教程中的方法整理的对象池实现思路图,可能有些简陋:
以及实现对象池时所用的脚本的功能图:
4.代码
废话不多说,下面贴出所用脚本的代码:
using System.Collections;using System.Collections.Generic;using UnityEngine;//作为静态方法public class GameObjectUtil { private static Dictionary<RecycleGameObject,ObjectPool> pools=new Dictionary<RecycleGameObject, ObjectPool>(); //提供一个实例化方法 public static GameObject Instantiate(GameObject prefab, Vector3 pos) { GameObject instance; RecycleGameObject reference = prefab.GetComponent<RecycleGameObject>(); //检查是否为可复用对象 if (reference!=null) { //取得该预制体的对象池 var pool= GetObjectPool(reference); //在对象池中生成克隆体,得到该克隆体 instance = pool.NextObject(pos).gameObject; return instance; } else { //调用monobehaviour自带的实例化方法直接生成克隆体 instance = GameObject.Instantiate(prefab); instance.transform.position = pos; return instance; } } /// <summary> /// 提供一个销毁方法 /// </summary> /// <param name="prefab">待克隆的预制体</param> public static void Destroy(GameObject prefab) { RecycleGameObject temp = prefab.GetComponent<RecycleGameObject>(); //检查是否为可复用对象 if (temp!=null) { temp.ShutDown(); } else { Destroy(prefab); } } /// <summary> /// 获取对象的对象池 /// </summary> /// <param name="reference"></param> /// <returns></returns> private static ObjectPool GetObjectPool(RecycleGameObject reference) { ObjectPool pool; //查询字典里有没有该对象相对应的对象池 if (pools.ContainsKey(reference)) { //得到相应的对象池 pool = pools[reference]; return pool; } else { //没有对象池的话新建一个对象池 var poolContainer=new GameObject(reference.gameObject.name+"pool"); //添加对象池管理组件 pool = poolContainer.AddComponent<ObjectPool>(); //将预制体绑定到对象池中 pool.prefab = reference; //将预制体与对象池添加到字典中 pools.Add(reference,pool); return pool; } }}
注:其中GameObjectUtil类为静态类,不需要继承monobehaviour类,也无需挂载到游戏对象中。
using System.Collections;using System.Collections.Generic;using UnityEngine;public class ObjectPool : MonoBehaviour { //对象池的管理脚本 public List<RecycleGameObject> poolInstance=new List<RecycleGameObject>(); public RecycleGameObject prefab; /// <summary> /// 创建预制体的克隆体 /// </summary> /// <param name="pos">克隆体的位置</param> /// <returns></returns> private RecycleGameObject CreateObject(Vector3 pos) { //实例化克隆体 var clone=GameObject.Instantiate(prefab); //设置克隆体的位置 clone.transform.position = pos; //将克隆体作为对象池的子对象 clone.transform.parent = transform; //将克隆体加入到列表中 poolInstance.Add(clone); return clone; } /// <summary> /// 取出克隆体 /// </summary> /// <param name="pos">克隆体的位置</param> /// <returns></returns> public RecycleGameObject NextObject(Vector3 pos) { RecycleGameObject instance = null; //调用方法获取克隆体实例 instance = CreateObject(pos); //激活克隆体 instance.Restart(); return instance; }}
using System.Collections;using System.Collections.Generic;using UnityEngine;public class RecycleGameObject : MonoBehaviour { //通过设置游戏对象的SetActive属性来激活/关闭游戏对象,并作为判断此物体是否为可复用对象的标准 public void Restart() { gameObject.SetActive(true); } public void ShutDown() { gameObject.SetActive(false); }}
5.使用方法
只需要在预制件里挂上RecycleGameObject脚本,就能将此物体作为可复用的物体。调用GameObjectUtil类里面的Instantiate方法就能实例化物体及其对象池。比如我要生成个对象池,里面有3个物体。那我可以这样写个脚本来调用。
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Test : MonoBehaviour{ public int mun; public GameObject prefab; private Vector3 pos; // Use this for initialization void Start () { pos = transform.position+Vector3.right; } // Update is called once per frame void Update () { if (mun>0) { GameObjectUtil.Instantiate(prefab,pos); mun--; } }}
在场景中放入一个Cube,挂载上此脚本,如图设置:
为脚本中的prefab指定物体,在这里我指定了一个Sphere,Sphere里挂载了RecycleGameObject脚本,运行情况如图:
可以看到对象池里有3个对象,且对象池中的物体都挂载了RecycleGameObject脚本。
- unity学习笔记#2--unity对象池
- unity学习笔记2
- unity学习笔记2
- Unity 学习笔记 2
- 【unity学习笔记】unity3d- 使用对象池高效管理内存
- Unity学习笔记(2) --- Unity脚本的生命周期
- UNITY SHADER学习笔记2(unity 5.6)
- unity学习笔记
- UNity学习笔记
- unity学习笔记
- Unity学习笔记
- unity学习笔记3
- Unity学习笔记.01
- unity学习阶段笔记
- unity学习笔记
- unity学习笔记1
- unity学习笔记3
- unity学习笔记4
- redis学习(1)python连接redis
- Spring 中的BeanUtils与apache中的BeanUtils用法与比较
- 40个Java多线程问题总结
- 数组指针和指针数组的区别
- iOS
- unity学习笔记#2--unity对象池
- FreeRTOS学习2--队列
- 世界地区选择
- Android 安装应用的两种方式--外部应用安装器安装和静默安装(系统应用)
- Eclipse servers插件安装
- 047、048、049-C++
- 端口与对应服务一览
- v4l2框架分析
- Mac安装mysql,忘记密码怎么办