Unity 遊戲物件池 極簡版
分類
說明
物件池是一種設計模式,在遊戲中有很多情況要不斷地產生遊戲物件,過沒多久後又被摧毀,例如:子彈。當大量的遊戲物件被實體化與摧毀導致遊戲出現延遲時,使用物件池的概念可以大幅提升效能,本篇將告訴大家物件池的概念和實作。
什麼是物件池
物件池(Object Pool)是一種軟體設計模式,用於提高物件的重複使用性和效能。它是一個儲存和管理物件的集合,這些物件在一段時間內被預先建立和初始化,並在需要時被重複使用,而不需要頻繁地創建和銷毀物件。
在生活中有很多物件池的例子,例如穿衣服,平常人們會買衣櫥將一些衣物、內衣褲放在衣櫥中,然後選一套穿在身上,你可以把衣櫥當作是池子(Pool),衣櫥裡面的衣物就當作是被預先建立和初始化好的物件,當你想穿衣服時就會從衣櫥拿一套衣服出來穿,髒了就拿去洗一洗,洗完曬乾再放回衣櫥,下次就不用再去買衣服了,可以直接拿衣櫥裡面的衣服穿,但就如現實情況一樣,衣櫥會佔用一點空間。
實作
此版本的物件池是我修改過的極簡版,用途是產生大量的需要重複使用的遊戲物件,遊戲初始化會產生指定數量的遊戲物件,當數量不足時,會自動擴大池子裡面的物件數量,池子容量沒有上限。
你可以依照自己的需求,進一步客製化自己的物件池。
GameObjectPool.cs
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 遊戲物件池
/// </summary>
public class GameObjectPool : MonoBehaviour
{
/// <summary>
/// 預製
/// </summary>
[SerializeField]
private GameObject prefab;
/// <summary>
/// 遊戲物件池
/// </summary>
private List<GameObject> pooledGameObjects;
/// <summary>
/// 一開始要產生的數量
/// </summary>
[SerializeField]
private int amountToPool;
private void Awake()
{
pooledGameObjects = new();
}
void Start()
{
GameObject _gameObject;
for (int i = 0; i < amountToPool; i++)
{
_gameObject = Instantiate(prefab, transform);
_gameObject.SetActive(false);
pooledGameObjects.Add(_gameObject);
}
}
/// <summary>
/// 取得一個物件,若池沒有物件,就會新增一個新的物件到池子當中
/// </summary>
/// <returns></returns>
public GameObject GetPooledGameObject()
{
foreach (GameObject pooledGameObject in pooledGameObjects)
{
if (!pooledGameObject.activeInHierarchy)
{
pooledGameObject.SetActive(true);
return pooledGameObject;
}
}
GameObject _gameObject = Instantiate(prefab, transform);
pooledGameObjects.Add(_gameObject);
return _gameObject;
}
}
使用方式
以下是一個球池的範例。
建立一個空遊戲物件,新增 GameObjectPool 組件,並設定好屬性。
要建立一顆球,可以這樣寫。
GameObjectPool ballPool = GameObject.Find("BallPool").GetComponent<GameObjectPool>();
GameObject ballGameObject = BallPool.GetPooledGameObject();
要回收一顆球,只需 SetActive(false)
ballGameObject.SetActive(false);
較詳細的工作流程,可參考我寫的 Ball 組件使用機制。
Ball.cs
using UnityEngine;
/// <summary>
/// 球
/// </summary>
public class Ball : MonoBehaviour
{
/// <summary>
/// 球池
/// </summary>
private static GameObjectPool ballPool;
/// <summary>
/// 球池
/// </summary>
public static GameObjectPool BallPool
{
get
{
if (ballPool == null)
{
ballPool = GameObject.Find("BallPool").GetComponent<GameObjectPool>();
}
return ballPool;
}
}
/// <summary>
/// 建立一顆球的遊戲物件
/// </summary>
/// <param name="position">球的位置</param>
/// <returns></returns>
public static GameObject CreateOneBall(Vector3 position)
{
GameObject ballGameObject = BallPool.GetPooledGameObject();
ballGameObject.transform.position = position;
return ballGameObject;
}
}
上面範例,CreateOneBall
可以產生一顆球並且指定位置,接著就可以在想要建立一顆球時使用靜態的方法獲得一顆球,並且指定位置。
GameObject ballGameObject = Ball.CreateOneBall(transform.position);
回收機制就是當球碰到某個區域時,例如:出界,就將球回收。
DeadZone.cs
using UnityEngine;
/// <summary>
/// 清除出界的遊戲物件
/// </summary>
public class DeadZone : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D other)
{
if (!other.gameObject.CompareTag("Ball"))
{
return;
}
other.gameObject.SetActive(false);
}
}
以上就是整個球的獲取和回收機制。
參考
一杯咖啡的力量,勝過千言萬語的感謝。
支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!