بهینه سازی بازی (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 یکی از مباحث مهم بهینه سازی بازی است که امیدوارم به پیاده سازی بهتر اون کمک کرده باشم.