Unity,unity3d

來源:互聯網
上載者:User

Unity,unity3d

孫廣東 2014.6.28

很早之前看到的外國文章,覺得不錯,分享一下, 對象池在AssetStore中也是有很多外掛程式的,但是有些重了,自己寫一個輕量的豈不是很好。

當你需要建立大量某種類型對象時,它可以方便地重新使用單個對象,而不是不斷地 建立/銷毀(操作會導致大量的記憶體回收)。此ObjectPool指令碼,產生和回收您的遊戲對象的對象池。
代碼:https://github.com/UnityPatterns/ObjectPool
http://unitypatterns.com/resource/objectpool/

特性:
?選擇性地池對象基於prefab類型
?簡單和運算式文法 對於 執行個體化和回收
?輕鬆地預先執行個體化對象,以防止運行時執行個體化
?搜尋和跟蹤所有產生/池子內的在情境中執行個體化的

怎麼使用?
通常情況下,當您執行個體化並銷毀prefabs的執行個體,您在運行時不斷建立新的對象和摧毀它們,這可能會導致運行時記憶體回收和偶爾的畫面播放速率下降。ObjectPool 可以防止這種,通過預先執行個體化,而不是被摧毀然後重建對象!

產生池子中的對象:
例如,如果我有能發射子彈對象的炮塔,我能建立 10 枚一模一樣的子彈對象並重新使用。子彈將永遠不會被銷毀,只是取消啟用、需要產生時重新啟用他們。
ObjectPool要做到這一點,你只要調用CreatePool() 產生指定Prefab的對象。


public class Turret : MonoBehaviour{    public Bullet bulletPrefab;    void Start()    {        //Create a pool with 10 pre-instantiated bullets in it        bulletPrefab.CreatePool(10);        //Or you could also pre-instantiate none, and the system will instantiate them as it needs them        bulletPrefab.CreatePool();    }}

現在你可以使用ObjectPool類中的Spawn() and Recycle() 來代替Instantiate() and Destroy()方法。例如,當搶發射子彈時,我產生子彈執行個體:

public class Turret : MonoBehaviour{    public Bullet bulletPrefab;    public void ShootBullet()    {        //Spawn a bullet at my position with my rotation        bulletPrefab.Spawn(transform.position, transform.rotation);    }}

當你想要回收這個執行個體,在你想要消失的組件或者對象上調用Recycle()函數。 當子彈發生碰撞時,我們將回收它。

public class Bullet : MonoBehaviour{    void OnCollisionEnter(Collider other)    {        //De-activate the object and return it to the spawn pool        gameObject.Recycle();        //You can also use this:        //this.Recycle();    }}

函數Spawn()被建立的對象的引用, 所以你能夠儲存這個對象或者調用它的其他方法. 這個函數不像Unity的 Instantiate(), 你不需要強制類型轉換得到 GameObject or Component.


小心用回收的對象!
現在,您的對象正在被回收和重新使用,你必須要小心,因為如果您的執行個體有任何變數被改變,您必須手動重設它們。你可以通過使用Unity提供的的 OnEnable() 和 OnDisable() 函數,只要您的執行個體使用spawned or recycled函數將會觸發OnEnable() 和 OnDisable()。

例如,這是不正確的:

public class Bullet : MonoBehaviour{    public float travelDuration;    float timer = 0; //Only gets set to zero once!    void Update()    {        timer += Time.deltaTime;        if (timer >= travelDuration)        {            gameObject.Recycle();        }    }}

為什麼不對呢?因為我們的timer變數計數,但永遠不會返回到零!所以當回收並在此使用時,它已經不是最開始的狀態了。我們可以很容易解決這個問題:

public class Bullet : MonoBehaviour{    public float travelDuration;    float timer;    void OnEnable()    {        //Correct! Now timer resets every single time:        timer = 0;    }    void Update()    {        timer += Time.deltaTime;        if (timer >= travelDuration)        {            gameObject.Recycle();        }    }}

現在我們的子彈正確重設他的timer變數。

你能通過對象引用預製體,在以前是不能的
GameObject現在有組件的擴充方法

InitialPoolSize 參數已添加到 CreatePool()函數總,並告訴它要預先執行個體化多少的對象,這些都是最初被隱藏和延遲產生的。
您還可以將 ObjectPool 附加到一個遊戲對象,通過inspector 設定要 預先執行個體化 的預製體
增益集函數已經添加了用於搜尋/統計 執行個體對象

如果你想要 RecycleAll 要使用衍生類別型,然後更改這:
var active = instance.prefabLookup.Keys.Where(p => p.GetType() == typeof(T).ToList();
to:
var active = instance.prefabLookup.Keys.Where(p => p is T).ToList();
也適用於 GetAllOfType 的類似的變化






著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.