مهدی رحمتی
مهدی رحمتی
خواندن ۷ دقیقه·۵ سال پیش

بهینه سازی بازی (1) : "Object Pool" به زبان ساده (بخش 2) + پیاده سازی

در بخش قبلی، از اینکه چرا از "Object Pool" استفاده میکنیم و چطور استفاده میکنیم، پرداخته شد. حالا میرسیم به بخش دوم:


نکته آغازین: از اونجایی که Pool همچنان مجموعه ای از آبجکت هارو همراه خودش داره، وقتی هم که باهاش کاری نداریم همچنان در حافظه باقی است و جلوی Garbage Collector رو میگیره. پس برای اینکه این اتفاق نیافته، هر موقع با Pool کاری نداشتیم، بهتره که تمامی اتصالات و Reference هایی که به Pool مربوط میشن رو از بین ببریم.

آیا ایجاد و حذف آبجکت ها، به CPU ربطی داره؟

قطعا همینطوره! فرایند Instantiate() و Destroy() برای انجام کارشون نیازمند یک کمک کوچیک از سمت CPU هستن.

حالا فکر کنید چندین آبجکت مرتب درخواست Instantiate() و Destroy() رو ارسال کنن. فاجعه رخ میده.

پس فرایند Object Pooling، هوای CPU رو هم داره!



object Pool در یک نگاه:



پیاده سازی Object Pool در موتور Unity 3D (نمونه ساده)

0. قبل از هر چیز، باید یک فایل C# در یونیتی ایجاد کنیم :)

using UnityEngine; using System.Collections.Generic; public class Object_Pooler : MonoBehaviour { }

1. چندتا متغییر کوچیک رو باید وارد کنیم:

public class Object_Pooler : MonoBehaviour { //آبجکتی که قصد داریم ازش در بازی زیاد استفاده کنیم public GameObject obj; //حد و مرز برای ایجاد آبجکت public int amount = 20; //آبجکت هایی که در ابتدای بازی ساخته میشن، داخل این لیست ذخیره و استفاده میشن public static List<GameObject> pooledObjects;}

2. حالا در نقطه استارت بازی، دستور میدیم که تمام آبجکت هارو ایجاد کن و در حالت "استراحت (غیرفعال)" قرار بده:

public class Object_Pooler : MonoBehaviour { //آبجکتی که قصد داریم ازش در بازی زیاد استفاده کنیم public GameObject _obj; //حد و مرز برای ایجاد آبجکت public int _amount = 20; //آبجکت هایی که در ابتدای بازی ساخته میشن، داخل این لیست ذخیره و استفاده میشن public static List<GameObject> _pooledObjects; void Start() { _pooledObjects = new List<GameObject>(); for (int i=0; i < _amount; i++) { // ایجاد اولیه GameObject new_obj = (GameObject)Instantiate(_obj); // آبجکت رو روی حالت &quotاستراحت(غیرفعال)&quot میگذاریم new_obj.SetActive(false); // آبجکتی که ایجاد کردیم رو به لیست اضافه میکنیم _pooledObjects.Add(new_obj); } } }

3. یک تابع برای استفاده از آبجکت های "درحال استراحت"، اضافه میکنیم:

public class Object_Pooler : MonoBehaviour { public static GameObject GetPooledObject() { for (int i=0; i < _pooledObjects.Count; i++) { //چک میکنیم که آبجکت مورد نظر غیرفعال باشد if (!_pooledObjects[i].activeInHierarchy) return _pooledObjects[i]; } return null; } }

4. حالا در یک اسکریپت دیگر، میتوانیم از Object Pool استفاده کنیم:

public class Gun : MonoBehaviour { void Update() { if (Input.GetMouseButtonDown(0)) Shoot(); } void Shoot() { // آبجکتی که در لیست وجود دارد و درحال استراحت است GameObject obj = Object_Pooler.GetPooledObject(); if (obj != null) { obj.transfrom.position = Vector3.zero; //فعالسازی obj.SetActive(true); } } }


5. در آخر، به آبجکتی که از Gun شلیک میشه، میگیم بعد از فلان کار انجام شده، غیرفعال شود:

مثلا بعد از 5 ثانیه، یا بعد از برخورد و...

توی این مثال، برخورد رو در نظر گرفتم:

public class Bullet : MonoBehaviour { private void OnTriggerEnter(Collider other) { if (other.tag == &quotPlayer&quot) gameObject.SetActive(false); } }


توی این مثال، زمان رو در نظر گرفتم:

public class Bullet : MonoBehaviour { void OnEnable() { Invoke(&quotDestroy&quot, 5f); } private void Destroy() { gameObject.SetActive(false); } private void OnDisable() { CancelInvoke(); } }


مبحث Object Pool یکی از مباحث مهم بهینه سازی بازی است که امیدوارم به پیاده سازی بهتر اون کمک کرده باشم.

بهینه سازیoptimizeunity
موسس تیم BlueAge - بازیساز
شاید از این پست‌ها خوشتان بیاید