码迷,mamicode.com
首页 > 编程语言 > 详细

Unity3D中对象池的实现

时间:2015-08-31 00:52:39      阅读:429      评论:0      收藏:0      [点我收藏+]

标签:

在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 }

这样使用对象池来重复利用子弹进行发射就完成了,而且只需要预设的名字不同,什么预设都可以往这个池子里面丢哦。

 

Unity3D中对象池的实现

标签:

原文地址:http://www.cnblogs.com/arios/p/4771991.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!