Object pooling is a great way to optimize your game and avoid memory leak you should implement this method on games in which you instantiate and destroy a lot of game objects this approach creates a game object pool and does not destroy this object only disables it and calls the same object when needed
it's a very modular reusable system in any kind of game
First of All Create A folder for Pooler like "ObjPooler" and ad those scripts
"CreateGameObjects" Script;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class CreateGameObjects : MonoBehaviour
{
public Transform Parent;
[SerializeField]
public List<Pool> gameObjectList;
private PoolDictionary poolDic;
[SerializeField]
private List<GameObject> gmSelectedGameObjects;
private Transform destinatinTransform;private static CreateGameObjects _instance;
public static CreateGameObjects Instance { get { return _instance; } }
void Awake()
{
// Makes object singleton so you can reach easily
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
}
else
{
_instance = this;
}
StartPooling();
}
public void StartPooling()
{
destinatinTransform = this.GetComponent<Transform>();
poolDic = GetComponent<PoolDictionary>();
poolDic.ResetPool();
poolDic.setPool(gameObjectList, Parent);
}
public GameObject CreateGameObject(string TagName, Vector3 pos, Transform parent)
{
return poolDic.SpawnFromPool(TagName, pos, parent);
}
public GameObject InstantiateObject(string TagName, Vector3 pos)
{
Pool item = gameObjectList.Where(x => x.tag == TagName).FirstOrDefault();
if (item != null)
{
return Instantiate(item.prefab, pos, Quaternion.identity);
}
return null;
}
public int AddOnScreenSelectedGameObject(GameObject gmObj)
{
gmSelectedGameObjects.Add(gmObj);
return gmSelectedGameObjects.IndexOf(gmObj); // last insterted index
}
public void RemoveOnScreenSelectedGameObject()
{
gmSelectedGameObjects.Clear();
}
}
"Pool" Script
[System.Serializable]
public class Pool
{
public string tag;
public GameObject prefab;
public int size;
}
"PoolDictionary" Script;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolDictionary : MonoBehaviour
{
//game objects queue
[HideInInspector]
public Dictionary<string, Queue<GameObject>> poolDictionary;
private List<Pool> _pool;
public void ResetPool()
{
_pool = new List<Pool>();
}
// starts objectpool
public void setPool(List<Pool> pool, Transform parent)
{
_pool = pool;
poolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (Pool item in _pool)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < item.size; i++)
{
GameObject gmObj = Instantiate(item.prefab);
gmObj.SetActive(false);
// gmObj.transform.SetParent(parent);
objectPool.Enqueue(gmObj);
}
poolDictionary.Add(item.tag, objectPool);
}
}
private void activateAllChildren(GameObject gm)
{
gm.SetActive(true);
for (int j = 0; j < gm.transform.childCount; j++)
{
gm.transform.GetChild(j).gameObject.SetActive(true);
}
}
// calls object from pool
public GameObject SpawnFromPool(string tag, Vector3 position, Transform parent)
{
if (!poolDictionary.ContainsKey(tag))
{
Debug.Log("Obj tag is not Found:" + tag);
return null;
}
GameObject spawnObj = poolDictionary[tag].Dequeue();
//makes selected gameobject active
activateAllChildren(spawnObj);
if (parent != null)
{
spawnObj.transform.SetParent(parent);
}
else
{
// transform.SetParent(parent);
}
spawnObj.transform.position = position;
spawnObj.transform.rotation = Quaternion.identity;
poolDictionary[tag].Enqueue(spawnObj);
return spawnObj;
}
}
you can implement those classes in any kind of project always the same to
showcase an example I have created a player and you can shoot with
"space" button
Here is my "PlayerShooter" Script;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerShooter : MonoBehaviour
{
[SerializeField]
Transform shootingPoint;
GameObject currentGameObj;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
currentGameObj= CreateGameObjects.Instance.CreateGameObject("Bullet", this.transform.position, null);
currentGameObj.transform.position = shootingPoint.transform.position;
}
}
}
And to Shoot Bullets here is my "BulletScript";
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletScript : MonoBehaviour
{
void Update()
{
// speed can be a serializefield its for demostration.
this.transform.position += Vector3.forward * 30F * Time.fixedDeltaTime;
}
private void OnCollisionEnter(Collision collision)
{
Debug.Log("Bullet Collision");
this.gameObject.SetActive(false);
}
}
and to start pooling you have to add Pool object to scene
as You see There is a Bullet object prefab it's a sphere with nothing fancy only a collider and rigid body added with all axes constraint as you see there is a very simple scene you need to add "PlayerShooter" Script to the player and "BulletScript" to Bullet and set Bullet tag"Bullet"
you may set bullet pool size any count you like based on your game needs
and you can add any kind of object to the pool system
So that's all for now if you have difficulties with implementation
please mail me I can send you the whole project or don't hesitate to ask
questions :)
happy coding :)
No comments:
Post a Comment