Вторник, 26 Ноября 2024, 06:39

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Создание пулов объектов
pixeyeДата: Среда, 18 Апреля 2012, 21:23 | Сообщение # 1
Red Winter Software
Сейчас нет на сайте
Ни для кого не секрет, что использованные объекты надо "чистить" и удалять со сцены. Однако в действительности это достаточно вредный процесс. Особенно когда мы говорим об объектах которые очень часто создаются/удаляются.

Это могут быть и мобы, и пули, или любые другие мелкие и возобновляемые объекты. Суть в том, чтобы не уничтожать а изначально вгрузить на уровень предполагаемое кол-во объектов и активировать их понадобности, возвращая потом обратно в пул.

Вот скрипт.
Обзывать обязательно GameObjectPool.cs
Code

using UnityEngine;
using System;
using System.Collections;
namespace pools
{
public class GameObjectPool {

     private GameObject _prefab;
     private Stack available;
     private ArrayList all;
         
     private Action<GameObject> initAction;
     private bool setActiveRecursively;
         
     // ---- getters & setters ----
     #region getters & setters
         
     // returns the prefab being used by the pool.
     public GameObject prefab {
      get { return _prefab; }
     }
         
     // returns the number of active objects.
     public int numActive {
      get { return all.Count - available.Count; }
     }
         
     // returns the number of available objects.
     public int numAvailable {
      get { return available.Count; }
     }
         
     #endregion
     // ---- constructor ----
     #region constructor
         
     public GameObjectPool(GameObject prefab, uint initialCapacity, Action<GameObject> initAction, bool setActiveRecursively) {
      this._prefab = prefab;
      this.initAction = initAction;
      this.setActiveRecursively = setActiveRecursively;
          
      available =    (initialCapacity > 0)    ? new Stack((int) initialCapacity)  : new Stack();
      all =  (initialCapacity > 0)    ? new ArrayList((int) initialCapacity)    : new ArrayList();
     }
         
     #endregion
     // ---- public methods ----
     #region public methods
         
     public GameObject Spawn(Vector3 position, Quaternion rotation) {
      GameObject result;
          
      if (available.Count == 0){
           
       // create an object and initialize it.
       result = GameObject.Instantiate(prefab, position, rotation) as GameObject;
           
       // run optional initialization method on the object
       if (initAction != null) initAction(result);
           
       all.Add(result);
           
      } else {
       result = available.Pop() as GameObject;
           
       // get the result's transform and reuse for efficiency.
       // calling gameObject.transform is expensive.
       Transform resultTrans = result.transform;
       resultTrans.position = position;
       resultTrans.rotation = rotation;
           
       SetActive(result, true);
      }
          
      return result;
     }
         
     public bool Destroy(GameObject target) {
      if (!available.Contains(target)) {
       available.Push(target);
           
       SetActive(target, false);
       return true;
      }
          
      return false;
     }
         
     // Unspawns all the game objects created by the pool.
     public void DestroyAll() {
      for (int i=0; i<all.Count; i++) {
       GameObject target = all[i] as GameObject;
           
       if (target.active) Destroy(target);
      }
     }
         
     // Unspawns all the game objects and clears the pool.
     public void Clear() {
      DestroyAll();
      available.Clear();
      all.Clear();
     }
         
         
      public bool Unspawn (GameObject obj)
     {
      if (!available.Contains (obj)) {
       // Make sure we don't insert it twice.
       available.Push (obj);
       SetActive (obj, false);
       return true;
       // Object inserted back in stack.
      }
      return false;
      // Object already in stack.
          
          
     }
         
     // Applies the provided function to some or all of the pool's game objects.
     public void ForEach(Action<GameObject> action, bool activeOnly) {
      for (int i=0; i<all.Count; i++){
       GameObject target  = all[i] as GameObject;
           
       if (!activeOnly || target.active) action(target);
      }
     }
         
         
      public void prePopulate (int num)
     {
      GameObject[] array = new GameObject[num];
      for (int i = 0; i < num; i++) {
       array[i] = Spawn (Vector3.zero, Quaternion.identity);
       SetActive (array[i], true);
      }
      for (int j = 0; j < num; j++) {
       Unspawn (array[j]);
      }
     }
         
     #endregion
     // ---- protected methods ----
     #region protected methods
         
     // Activates or deactivates the provided game object using the method
     // specified by the setActiveRecursively flag.
     protected void SetActive(GameObject target, bool value) {
      if (setActiveRecursively) target.SetActiveRecursively(value);
      else target.active = value;
     }
         
     #endregion
}
}


Как пользоваться. В скрипте где создаем пул объектов прописываем в начале

using pools;

Code

GameObjectPool bulletPull;
public GameObject bulletPrefab;


наши переменные, bulletPrefab хранит объект пули который будет загружен в сцену.

Code

void Start(){     
      bulletPull = new GameObjectPool(bulletPrefab,99,bulletHandler,true);
                    bulletPull.prePopulate(99);
}

void bulletHandler(GameObject target){     
target.name = "bullet";
}



-
Code
bulletPull = new GameObjectPool(bulletPrefab,99,bulletHandler,true);
= создаем новый пул
первый аргумент это игровой объект который надо создать, второй это начальное кол-во, третий аргумент запускает функцию для установки первоначальных данных для объектов если они есть, последний аргумент либо деактивирует только объект, либо объект и его дочерние объекты если таковы имеются.
Code
bulletPull.prePopulate(99);
- сразу создаем на сцене 99 объектов пуль.

Code
void bulletHandler(GameObject target){     
target.name = "bullet";
}

Стартовая функция для созданных объектов пула - обязательно должна иметь аргумент игрового объекта ( это только что созданная пуля в нашем примере), собственно тут можно прописать все начальные параметры для объекта.

Все - теперь нам нужно правильно активировать объект и при необходимости возвращать его обратно в пул.

Code
bulletPull.Spawn (new Vector3 (0, 0, 0), Quaternion.identity);
- Spawn отвечает за активацию объекта из пула по позиции и вращению.
Возврат в пул выглядит так:
Code
bulletPull.Unspawn(myGameObject);
- где myGameObject - игровой объект который нужно вернуть обратно в конкретный (bulletPull) пул.

Автор (JS)


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю



Сообщение отредактировал pixeye - Среда, 18 Апреля 2012, 21:32
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг