一、unity3D對象池————單個對象在池中的創建


 

對象池:對象存儲在一個池子中,當需要再次使用時取出,而不需要每次都實例化一個新的對象,將對象循環利用起來。當我們需要大量實例化對象時可采用對象池,如游戲中的子彈等物體,當我們玩射擊類游戲時,要發射大量子彈,如果每發子彈直接通過Instantiate全部實例化(筆者在unity中試過大量Instantiate后不銷毀,unity引擎直接崩潰了),當然還有打怪類游戲,小怪的生成等。

下面有個小例子

 

對象池腳本(單例腳本)主要有以下三個部分

 

1、創建一個集合,當做你的對象池,用來存儲對象

 

2、一個取對象的方法

 

3、一個存對象的方法

 

一、創建一個對象池腳本ObjectPools,將腳本設置成單例(單例在Unity中經常使用到),不用掛在任何物體上

注:集合中Add(),添加后,自動添加在集合末尾  Remove()刪除元素時,假設刪除第一個元素,集合中的元素自動向前補位(詳情看另一篇集合泛型)

 1 public class ObjectPools : MonoBehaviour {
 2     //創建集合作為對象池
 3     List<GameObject> pools = new List<GameObject>();
 4     //單例
 5     private static ObjectPools instance;
 6     private ObjectPools() { }
 7     public static ObjectPools GetInstance()
 8     {
 9         if (instance==null)
10         {
11             //創建一個名字為ShellPool的對象,並將單例腳本附上
12             instance = new GameObject("ShellPool").AddComponent<ObjectPools>();
13         }
14         return instance;
15        
16     }
17     //從對象池中取對象
18     public GameObject MyInstantiate(GameObject name)
19     {
20         //對象池中沒有對象  實例化對象
21         if (pools.Count==0)
22         {
23             return Instantiate(name, Vector3.zero, Quaternion.identity) as GameObject;
24         }
25         else
26         {
27             //如果池中有對象 取出第一個
28             GameObject go = pools[0];
29             //將對象設置激活狀態
30             go.SetActive(true);
31             //從對象池中刪除對象
32             pools.Remove(go);
33             return go;
34 
35         }
36     }
37     //向對象池存對象
38     public void DelayInstantiate(GameObject name)
39     {
40         //隱藏對象
41         name.SetActive(false);
42         //放入對象池中(集合中)
43         pools.Add(name);
44     }
45 }

二、創建一個GameManager腳本,控制物體生成(預制體放在Resources文件下)

 1 public class GameManager : MonoBehaviour {
 2     GameObject shellPrefab;
 3     public void Awake()
 4     {
 5         //找到預制體
 6         shellPrefab = Resources.Load("Part01/Prefabs/Shell") as GameObject;  
 7     }
 8     private void Update()
 9     {
10         if (Input.GetMouseButtonDown(0))
11         {
12             //實例化對象
13             ObjectPools.GetInstance().MyInstantiate(shellPrefab);           
14         }
15     }
16 }

三、預制體腳本,掛在預制體上,控制子彈向前

 1 public class Shell : MonoBehaviour {
 2     Transform target;
 3     private void OnEnable()
 4     {
 5         //找到要生成的對象的空物體 位置,將空物體位置賦給對象初始位置
 6         target = GameObject.Find("GameBullet").transform;
 7         transform.position = target.position;
 8         //啟動協程 延時兩秒
 9         StartCoroutine(DelayObject(2f));
10     }
11     private void Update()
12     {
13         //物體移動
14         transform.Translate(Vector3.forward * Time.deltaTime * 10);
15     }
16     //協程 
17     IEnumerator DelayObject(float time)
18     {
19         yield return new WaitForSeconds(time);
20         //調用腳本 向對象池存對象
21         ObjectPools.GetInstance().DelayInstantiate(gameObject);
22     }
23 
24 }

 

小結:對象池創建一部分對象,使用對象后,不銷毀對象,通過隱藏對象,讓人感覺被銷毀,待下次需要繼續使用時,通過激活之前被隱藏的對象,減少了實例化消耗內存的缺點。但因為創建對象后,對象只是隱藏,未被銷毀,在運行時,還是可能占用大量內存。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM