[置顶] unity中对象池的使用
2016-02-15 10:52
429 查看
在我们做游戏的时候,总会听到一些高大上的专业词汇,并且认为这些知识是很难学习的,其实不然,只要我们认真的学习它,总有拨开云雾的时候。
对象池:可以重复利用资源,不用不断的销毁生成对象,大大减少cpu开销,还可以避免内存泄露
对于对象池,我们也可以参考一下内存池的设计思路:http://blog.csdn.net/shawngucas/article/details/6574863
在学习对象池之前我们先要考虑什么地方会用到对象池:
(1)当需要不断重复的创建,删除同一个对象时;
(2)当在一个场景中有大量的怪物时,它们会释放技能;群体攻击技能时, 因为每个人身上都要产生一个技能特效。技能都是用粒子特效做的,虽然Unity中粒子特效也是一个GameObject.但是 Particle System这个组件太特殊了。Instantiate以后会自动的执行脚本的初始化工作,Particle
System组件肯定也是个脚本,虽然我们看不到它实现的方式,但是Instantiate以后它定会先执行Awake()和OnEnable()一类初始化的方法。
那对象池的原理到底是什么呢,就是在我们创建出来物体后,当需要删除的时候并不是将它Destroy掉,而是将它SetActive(false);只是在场景中不显示并把它添加到字典或列表中,以备下次使用时不是去Instantiate(),而是从字典或列表中取出这个物体并对它的信息进行重置(包括SetActive(true))。我想在这个时候大家就明白了对象池的原理了,也没有大家想象中的那么难。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour {
//单例模式
public static ObjectPool Instance;
//创建一个字典key为string类型,value为ArrayList类型
private Dictionary<string, ArrayList> pool = new Dictionary<string, ArrayList>();
// Use this for initialization
void Start () {
Instance = this;
}
//根据形参来获取到我们需要的物体
public Object GetPool_Obj(string prefabName,Vector3 pos,Quaternion rot)
{
//在这有我才有Resources.Load()加载方式,所以预制物体要放在Resources文件夹下,在创建后名字后面都被加了一个Clone;
string key = prefabName + "(Clone)";
Object obj;
//根据key判断字典里有没有这个物体,如果有则取出来,然后重置,否则就创建一个
if(pool.ContainsKey(key)&&pool[key].Count>0)
{
ArrayList list = pool[key];
obj = list[0] as Object;
list.RemoveAt(0);
(obj as GameObject).SetActive(true);
(obj as GameObject).transform.position = pos;
(obj as GameObject).transform.rotation = rot;
}
else
{
obj = Instantiate(Resources.Load(prefabName), pos, rot);
}
//下面2行就是在被创建出来的物体上所绑定的脚本,用来调用ReturnPool_Obj();
DelayDestroy delay = (obj as GameObject).GetComponent<DelayDestroy>();
delay.Init();
return obj;
}
//将物体添加到字典中
public Object ReturnPool_Obj(GameObject obj)
{
string key = obj.name;
if(pool.ContainsKey(key))
{
ArrayList list = pool[key];
list.Add(obj);
}
else
{
pool[key] = new ArrayList { obj};
}
obj.SetActive(false);
return obj;
}
}
上面的cs就是对象池脚本,下面的是创建物体上绑定的脚本中对ReturnPool_Obj()调用。
public void Init()
{
StartCoroutine(ReturnToPool());
}
IEnumerator ReturnToPool()
{
yield return new WaitForSeconds(2);
ObjectPool.Instance.ReturnPool_Obj(this.gameObject);
}
当然你可以根据项目的需要而自己设定,我这里是用协同的方法在2s后调用。
好了,对于对象池的理解我也只是小猪,谢谢大家!
对象池:可以重复利用资源,不用不断的销毁生成对象,大大减少cpu开销,还可以避免内存泄露
对于对象池,我们也可以参考一下内存池的设计思路:http://blog.csdn.net/shawngucas/article/details/6574863
在学习对象池之前我们先要考虑什么地方会用到对象池:
(1)当需要不断重复的创建,删除同一个对象时;
(2)当在一个场景中有大量的怪物时,它们会释放技能;群体攻击技能时, 因为每个人身上都要产生一个技能特效。技能都是用粒子特效做的,虽然Unity中粒子特效也是一个GameObject.但是 Particle System这个组件太特殊了。Instantiate以后会自动的执行脚本的初始化工作,Particle
System组件肯定也是个脚本,虽然我们看不到它实现的方式,但是Instantiate以后它定会先执行Awake()和OnEnable()一类初始化的方法。
那对象池的原理到底是什么呢,就是在我们创建出来物体后,当需要删除的时候并不是将它Destroy掉,而是将它SetActive(false);只是在场景中不显示并把它添加到字典或列表中,以备下次使用时不是去Instantiate(),而是从字典或列表中取出这个物体并对它的信息进行重置(包括SetActive(true))。我想在这个时候大家就明白了对象池的原理了,也没有大家想象中的那么难。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour {
//单例模式
public static ObjectPool Instance;
//创建一个字典key为string类型,value为ArrayList类型
private Dictionary<string, ArrayList> pool = new Dictionary<string, ArrayList>();
// Use this for initialization
void Start () {
Instance = this;
}
//根据形参来获取到我们需要的物体
public Object GetPool_Obj(string prefabName,Vector3 pos,Quaternion rot)
{
//在这有我才有Resources.Load()加载方式,所以预制物体要放在Resources文件夹下,在创建后名字后面都被加了一个Clone;
string key = prefabName + "(Clone)";
Object obj;
//根据key判断字典里有没有这个物体,如果有则取出来,然后重置,否则就创建一个
if(pool.ContainsKey(key)&&pool[key].Count>0)
{
ArrayList list = pool[key];
obj = list[0] as Object;
list.RemoveAt(0);
(obj as GameObject).SetActive(true);
(obj as GameObject).transform.position = pos;
(obj as GameObject).transform.rotation = rot;
}
else
{
obj = Instantiate(Resources.Load(prefabName), pos, rot);
}
//下面2行就是在被创建出来的物体上所绑定的脚本,用来调用ReturnPool_Obj();
DelayDestroy delay = (obj as GameObject).GetComponent<DelayDestroy>();
delay.Init();
return obj;
}
//将物体添加到字典中
public Object ReturnPool_Obj(GameObject obj)
{
string key = obj.name;
if(pool.ContainsKey(key))
{
ArrayList list = pool[key];
list.Add(obj);
}
else
{
pool[key] = new ArrayList { obj};
}
obj.SetActive(false);
return obj;
}
}
上面的cs就是对象池脚本,下面的是创建物体上绑定的脚本中对ReturnPool_Obj()调用。
public void Init()
{
StartCoroutine(ReturnToPool());
}
IEnumerator ReturnToPool()
{
yield return new WaitForSeconds(2);
ObjectPool.Instance.ReturnPool_Obj(this.gameObject);
}
当然你可以根据项目的需要而自己设定,我这里是用协同的方法在2s后调用。
好了,对于对象池的理解我也只是小猪,谢谢大家!
相关文章推荐
- Unity3d纹理旋转
- unityTaidou(五)unity中委托事件
- Unity开发中总结的一些小技巧
- UnityNetwork
- unity, ugui button 禁止重复点击
- unity3d 资源打包加密
- Unity3D + ulua simpleframework的问题汇总
- unity3d 调用windows窗口
- [置顶] unity中NavMesh组件及使用介绍
- unity3d纹理格式设置
- unity3d Gizmos 画圆
- Unity插件_____DoTween(二)
- unity游戏数据的几种形式
- Unity Android 不显示阴影
- 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(55)-工作流设计-表单布局
- [基础知识] 总结使用Unity 3D优化游戏运行性能的经验
- Unity打造简易的GalGame游戏剧本编辑引擎
- unity3d 在2D空间中让一个点注视另一个点
- unity
- unity awake start 的区别