Trong bài này bạn Hải Nam có chia sẻ các xử lý pool qua game của bạn ấy để tối ưu việc quản lý đạn, việc xử lý này rất quan trọng trong quá trình các bạn quản lý các đối tượng trong game, giúp tăng tốc độ cho game, có gì các cứ comment để trao đổi thêm nhé.
Các bạn có thể đọc thêm bài tham khảo tại đây để hiểu thêm:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunController : MonoBehaviour
{
[SerializeField] GameObject BulletPrefabs; // Viên đạn
[SerializeField] Transform shootPoint; // Điểm bắn đạn
[SerializeField] BulletShoot DestroyBullet; // Hàm dùng để hủy viên đạn
[SerializeField] AudioSource ShootSound; // Tiếng bắn đạn
[SerializeField] float shootCoolDown; // Thời gian cách đoạn để bắn đạn
[SerializeField] List<GameObject> bullets; // list này chứa pool object dùng để active
public int ArBullet = 30; // Số lượng đạn cần có
float coolDown; // Là thời gian liên tục giảm theo deltatime nhằm kiểm tra độ trễ bắn đạn
// Start is called before the first frame update
void Start()
{
}
private void Awake()
{
// Khởi tạo 30 viên đạn và inactive 30 viên
bullets = new List<GameObject>();
for (int i = 0; i < 30; i++)
{
GameObject bullet_ = Instantiate(BulletPrefabs);
bullet_.SetActive(false); // Viên đạn inactive
bullets.Add(bullet_);
}
}
// Update is called once per frame
void Update()
{
coolDown -= Time.deltaTime;
shoot();
}
void shoot()
{
if (Input.GetKey(KeyCode.Space) && coolDown <= 0 && ArBullet > 0)
{
ShootSound.Play();
ArBullet–;
GameObject Bulletclone = null; // Đặt viên đạn bắn ra là rỗng
for (int i = 0; i < bullets.Count; i++)
{
if (!bullets[i].activeInHierarchy)
{
Bulletclone = bullets[i];
break;
}
}
// Nếu trong trường hợp là không tồn tại viên đạn nào trong list cả vì tất cả đã bắn hết rồi thì sẽ khởi tạo mới một viên đạn và
// Tự động add vào list luôn.
// Tránh lãng phí thêm tài nguyên cho các lần bắn sau
// (Thực tế thì ở đây đã setup giới hạn đạn nên sẽ ko bị trường hợp này,
// nhưng vẫn áp dụng trong trường hợp các game bắn súng phi thuyền.)
if (Bulletclone == null)
{
Bulletclone = Instantiate(BulletPrefabs);
bullets.Add(Bulletclone);
}
Bulletclone.transform.position = shootPoint.position;
Bulletclone.SetActive(true);
StartCoroutine(WaitAndReturnBullet(Bulletclone, 3f));
coolDown = shootCoolDown;
}
}
IEnumerator WaitAndReturnBullet(GameObject bullet, float time)
{
// Đợi một khoảng thời gian
yield return new WaitForSeconds(time);
// Kiểm tra nếu như viên đạn thuộc danh sách Pooling object
// Nếu có chạy hàm return bullet để nó trả object về list inactive
if (bullets.Contains(bullet))
{
ReturnBullet(bullet);
}
}
// Hàm trả viên đạn về trạng thái ko kích hoạt
public void ReturnBullet(GameObject bulletReturn)
{
bulletReturn.SetActive(false);
}
}
// hàm SpawnFromPool tạo thêm Object gắn vào Queue khi mà số lượng object khởi tạo ban đầu đã được bóc ra khỏi Queue để sử dụng
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager : MonoBehaviour
{
[System.Serializable]
public class Pool
{
public string name;
public GameObject prefab;
public int size;
}
[SerializeField]
public List<Pool> pools;
public Dictionary<string, Queue<GameObject>> PoolDictionary;
public static PoolManager Instance;
private void Awake()
{
Instance = this;
}
// Start is called before the first frame update
void Start()
{
PoolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (Pool pool in pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = CreateObj(pool.prefab);
objectPool.Enqueue(obj);
}
PoolDictionary.Add(pool.name, objectPool);
}
}
// Update is called once per frame
void Update()
{
}
public GameObject SpawnFromPool(GameObject gameObject, Vector3 position, Quaternion rotation)
{
if (!PoolDictionary.ContainsKey(gameObject.name))
{
return null;
}
GameObject objectToSpawn;
if (PoolDictionary[gameObject.name].Count == 0)
{
objectToSpawn = CreateObj(gameObject); // extend more gameobject
}
else
{
objectToSpawn = PoolDictionary[gameObject.name].Dequeue();
}
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
return objectToSpawn;
}
public void ReturnToPool(GameObject obj)
{
obj.SetActive(false);
PoolDictionary[obj.name].Enqueue(obj);
}
#region
public GameObject CreateObj(GameObject gameObject)
{
GameObject obj = Instantiate(gameObject, this.transform);
obj.name = gameObject.name;
obj.SetActive(false);
return obj;
}
#endregion
}
thanks
Bổ ích lắm a ơi