关于Unity3D中对象池的创建与回收
来源:互联网 发布:阿里云控制台 编辑:程序博客网 时间:2024/06/02 06:24
写的第一篇博客,说实话是有点激动的,以后每个周会留下我的一些学习笔记与感想,将会一直学习下去,欢迎一起交流学习, QQ:1059213621
对象池:在激活对象时,它从池中提取。在停用对象时,它放回池中,等待下一个请求。
作用:我的认识不够全面,单纯的认为是为了避免节约电脑内存的一种方法,使用对象池后,就不需要生成对象,然后再销毁,不断的创建和销毁本身是很消耗电脑内存的。(如有更好的更深度的认识欢迎交流)
首先是新建一个工程,在Assets下创建一个文件夹命名为Resources(创建这个文件夹的作用在于存放我们的预设体和脚本,当然生成的对象也要在这个文件夹里面用来Resources.Load),然后在Hierarchy面板里面创建一个Sphere(创建一个球),然后把这个球拖成预设体,
本次一共有五个脚本,分别为:
Subpool:对象池用于存放 相同类型 的游戏对象,不需要继承与MonoBehaviour;
IControl:接口类 : 用于管理对象的卵生和回收;
PoolControll:用于管理存放各种类型的游戏对象的对象池 管理类以K-Value来管理;
Sphere 和 Player脚本用来测试,将这两个脚本挂载到Sphere的身上,连续按下空格键实现对象池的回收和创建效果(当对象生成3s后,及活性设置为false),可以亲自尝试一下,
接下来是代码实现:
创建一个脚本命名为 Subpool
using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 1、从对象池中取一个游戏对象/// 2、回收某一个游戏对象/// 3、回收所有游戏对象/// 4、检查某个游戏对象是否在池子里/// </summary>public class Subpool { //对象池,里面存放场景中所需要的游戏对象 List<GameObject> pool = new List<GameObject> (); //要创建的游戏物体的预设体 GameObject prefab; //返回预设体的名字,预设体的名字和对象池的名字一致 //在管理对象池的类里面,可以通过预设体的名字找到相对应的对象池 public string name{ get{ return prefab.name; } } //自定义构造方法 public Subpool(GameObject obj){ prefab = obj; } //1、从对象池中获取一个对象 public GameObject SubPoolSpawn(){ GameObject obj = null; //遍历集合中所有的对象。如果有,就拿来用,如果没有,就创建 foreach (GameObject item in pool) { //如果游戏对象处于未激活状态,说明该对象可用 if (item.activeSelf == false) { obj = item; break; } } //对象池里面没有可用的对象 if (obj == null) { //创建一个新的游戏对象 obj = GameObject.Instantiate(prefab) as GameObject; //把新创建的游戏对象加入到池子里面 pool.Add(obj); } //游戏对象的状态设置为激活状态 obj.SetActive (true); //通过子类实例化接口对象,子类的脚本组件继承并实现了接口中的方法 // control里面存的就是该类实现的方法 //这个地方的游戏对象暂时就是一个子弹,但是需要继承IControl接口 IControl control = obj.GetComponent<IControl>(); if (control != null) { control.Spwan (); } return obj; } /// 2、回收某一个游戏对象 public void SubPoolUnSpawn(GameObject obj){ //如果对象池的集合包含该游戏对象 if (SubpoolContains(obj)) { IControl control = obj.GetComponent<IControl> (); control.UnSpwan (); } //设置激活性 obj.SetActive(false); } // 3、回收所有游戏对象 public void SubPoolUnSpawnAll(GameObject obj){ //遍历对象池 foreach (GameObject item in pool) { if (item.activeSelf == true) { //回收对象 SubPoolUnSpawn (item); } } } // 4、检查某个游戏对象是否在池子里 public bool SubpoolContains(GameObject obj){ //返回 return pool.Contains (obj); }}
然后继续创建一个脚本命名为 IControl这是一个接口类
using System.Collections;using System.Collections.Generic;using UnityEngine;//接口类 : 用于管理对象的卵生和回收public interface IControl { //卵生对象 void Spwan(); //回收对象 void UnSpwan();}
再创建一个脚本(命名为 : PoolControl)用于管理存放各种类型的游戏对象的对象池,管理类以K-Value来管理脚本内容是:
1、是一个单例类;
2、有添加对象池的方法;
3、通过找到对象调用对象池里面创建的游戏对象的方法返回;
4、回收游戏对象;
下面是具体脚本内容:
using System.Collections;using System.Collections.Generic;using UnityEngine;public class PoolControll{ #region 单例 //内建静态实例 private static PoolControll instance; //构造⽅方法必须设为私有 private PoolControll(){ } public static PoolControll Instance { get{ if(instance == null) { instance = new PoolControll();//为实例初始化 } return instance; } } #endregion //创建字典,根据预设体的名字,找到对象池 //存放各种类型的的对象池的集合 Dictionary<string,Subpool> poolDic = new Dictionary<string, Subpool>(); //1、添加对象池,外界不能来调用 private void Register(string name){ //根据名字去创建池子 GameObject obj = Resources.Load(name) as GameObject; Subpool pool = new Subpool (obj); //把池子添加到字典里 poolDic.Add(name,pool); } //2、获取对象池里面额游戏对象 public GameObject Spawn(string name){ //如果没有这个游戏对象对应的池子 if (!poolDic.ContainsKey(name)) { Register (name); } //根据名字找到池子 Subpool pool = poolDic[name]; return pool.SubPoolSpawn (); } //回收一个游戏对象 public void UnSpawn(GameObject obj){ //遍历所有的池子 foreach (Subpool pool in poolDic.Values) { //如果对象池里面包含这个游戏对象 if (pool.SubpoolContains(obj)) { pool.SubPoolUnSpawn (obj); break; } } }}
然后再次创建两个脚本命名为 :Sphere 和 Player
注意:这个脚本用来测试对象池是否成功
Sphere脚本如下:
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Bullet : MonoBehaviour,IControl { void Start () { } //卵生对象 public void Spwan(){ //为了测试,我们在取出一个对象后,让它3S中收回 Invoke ("BulletUnSpawn", 3f); print ("从对象池中取出一个游戏对象"); } //回收对象 public void UnSpwan(){ print ("把游戏对象回收到对象池了"); } void BulletUnSpawn(){ //回收游戏对象 PoolControll.Instance.UnSpawn(gameObject); //重置游戏对象 transform.position = Vector3.zero; } void Update () { transform.position += Vector3.forward * Time.deltaTime * 50; }}
Player脚本如下所示:
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Player : MonoBehaviour { // Update is called once per frame void Update () { if (Input.GetKeyDown(KeyCode.Space)) { PoolControll.Instance.Spawn ("Sphere"); } }}
- 关于Unity3D中对象池的创建与回收
- 关于构造方法与对象的创建
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 【技术】在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 在Unity3D中动态创建对象和创建Prefab原型对象的三种方式
- 关于Java的对象的创建和回收机制的小结
- c++中关于类对象的创建
- 关于js中动态创建对象的
- 对象的创建、回收、new和malloc
- Unity3D中对象池的使用
- Unity3D中对象池的使用
- Unity3d中对象池(ObjectPool)的实现
- 对Unity3D中对象池的尝试
- 升级内存,插上两个内存条显示单通道,怎么设置为双通道
- 域名解析过程
- Subtree with Maximum Average
- MQTT协议(三) PUBLISH
- TTF 字体文件 删除不了,提示已经在System 打开
- 关于Unity3D中对象池的创建与回收
- 问题 M: 因子个数
- Mac下配置Tomcat,输入startup.sh后提示command not found
- android启动activity的详细过程
- 网络流 飞行员配对方案问题
- Hibernate入门(三)简单CRUD
- 用ssh公钥实现免密码登录
- MemCache分布式内存对象缓存系统
- How to traverse a directory tree