标签:
在Unity中常常会遇到需要重复创建,销毁某些物体的情况,比如fps类游戏中的子弹,rpg类游戏中的小怪等等,如果直接使用Instantiate和Destroy的话,会浪费系统的资源,而使用对象池则能够节省下这些浪费。
这里使用一个重复利用子弹的进行发射的简单场景来演示对象池。
首先需要一个在场景中创建一个Cube,充当子弹。
然后在Assets目录下创建Resources文件夹,在Cube上添加上刚体,取消重力后,将Cube拖入Resources文件夹内作为一个预设,在场景中删除这个Cube。
创建对象池的脚本,由于对象池需要在全局中被调用,因此对象池脚本使用单例模式会比较方便使用。
在摄像机上挂上ObjectPoolMag脚本。
1 public class ObjectPoolMag : MonoBehaviour { 2 public static ObjectPoolMag _instance; 3 private Dictionary<string, Stack> pool = new Dictionary<string, Stack>(); 4 5 void Awake() { 6 _instance = this; 7 } 8 9 public GameObject Get(string prefabName,Vector3 position,Quaternion rotation) { 10 11 string key = prefabName + "(Clone)"; 12 GameObject getItem; 13 if (pool.ContainsKey(key) && pool[key].Count > 0) 14 { 15 Stack list = pool[key]; 16 getItem = list.Pop() as GameObject; 17 getItem.SetActive(true); 18 getItem.transform.position = position; 19 getItem.transform.rotation = rotation; 20 } 21 else 22 { 23 getItem = Instantiate(Resources.Load(prefabName), position, rotation) as GameObject; 24 } 25 getItem.GetComponent<Des>().Init(); // 初始化相关状态 26 return getItem; 27 } 28 29 public void Return(GameObject go) 30 { 31 string key = go.name; 32 if (pool.ContainsKey(key)) 33 { 34 Stack list = pool[key]; 35 list.Push(go); 36 } 37 else 38 { 39 pool[key] = new Stack(); 40 pool[key].Push(go); 41 } 42 go.gameObject.SetActive(false); 43 } 44 }
这个脚本提供了一个从对象池中获取gameObject和放回gameObject的方法,当需要获取一个物体时,会首先通过这个物体的名字进行一次判断,如果字典中已经存在了存放该名字的栈且栈内元素的个数大于0时,直接从栈内Pop出该gameObject
如果没有或者栈已经空了的情况下,则使用Instantiate来创建一个新的gameObject。
然后是具体的应用,在摄像机上再挂上一个脚本Fire来实现子弹的发射
1 public class Fire : MonoBehaviour { 2 void Update () { 3 if (Input.GetButtonDown("Fire1")) { 4 GameObject o = ObjectPoolMag._instance.Get("Cube", transform.position, Quaternion.identity); 5 o.GetComponent<Rigidbody>().AddForce(0, 0, 500); 6 } 7 } 8 }
最后在Cube的预设上添加一个Des脚本来控制Cube的消失。
这里使用了携程,使Cube在5秒后消失。
1 public class Des : MonoBehaviour { 2 public void Init() { 3 StartCoroutine(ReturnToPool()); 4 } 5 6 IEnumerator ReturnToPool() { 7 yield return new WaitForSeconds(5f); 8 ObjectPoolMag._instance.Return(this.gameObject); 9 } 10 }
这样使用对象池来重复利用子弹进行发射就完成了,而且只需要预设的名字不同,什么预设都可以往这个池子里面丢哦。
标签:
原文地址:http://www.cnblogs.com/arios/p/4771991.html