The question is answered, right answer was accepted
Can someone post a generic object pool script?
From what I can see everyone tells you that you need to use object pools. But finding a generic object pool script is way to hard for how common it's said to be. So can someone post a C# and maybe a java script example that I can use, modify and point other programmers to?
It should have a example "Activate and set to position" method that is public.
The interface in the Inspector should look like this:
//
Object to pool [game object/transform/whateveryouusetoimporttheobject ]
Number to create [int]
//
That's all I am asking for. Simple code that anyone can use and modify.
I had downvoted you for asking for a script but you redeemed yourself by posting your findings and workable answer.
https://unity3d.com/learn/tutorials/topics/scripting/object-pooling is exactly what you're looking for.
Answer by fafase · Aug 06, 2014 at 09:14 PM
EDIT: My own implementation of ObjectPool It probably could benefit some modification, I don't claim it to be perfect, it just works for me.
Here is a tutorial from Unity http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/object-pooling
The basic idea is to have a class that will store a list of game object, first you create:
List<GameObject>list;
public PoolSystem(int size, GameObject prefab){
list = new List<GameObject>();
for(int i = 0 ; i < size; i++){
GameObject obj = (GameObject)Instantiate(prefab);
list.Add(obj);
}
}
This is the constructor of your pool. It takes a size and what object you want to store.
Then it has a method to get the first of the list
public GameObject GetObject(){
if(list.Count > 0){
GameObject obj = list[0];
obj.RemoveAt(0);
return obj;
}
return null;
}
this one is simplified as if you are sure of the list you can skip the check and if you don't want to return null, you can create a new obect to be added to the list.
The point of taking the first of a list is that you do not have to search for a free one while using the array.
The other part is to reassign the object to the pool:
public void DestroyObjectPool(GameObject obj){
list.Add(obj);
obj.SetActive(false);
}
Finally you may want to clear the pool:
public void ClearPool(){
for(int i = list.Count - 1; i > 0; i--){
GameObject obj = list.RemoveAt(i);
Destroy(obj);
}
list = null;
}
Though this last part is only useful if you need to clear a pool but if you do all properly you should not need that since the point of a pool is that you do not have to create and destroy, just create. The GC will take care of removing it all
I use List over Stack or Queue because it goes faster according to a test I did a while ago. You could also look here :
http://msdn.microsoft.com/en-us/library/ff458671%28v=vs.110%29.aspx
but I have never used nor seen ConcurrentBag apart from that example.
I suspect ConcurrentBag wouldn't be available in $$anonymous$$ono.
Why are there so many object pool scripts (like this one) that have you taking the object out of the list? It really is not necessary. It actually is costing you power to take it out and when you are done with it put it back in again. It's not like there are things that you can't do without removing it from the list.
Removing it from the list has some advantages.
You don't have to search through the list to find a valid GameObject
If something unusual happens to the object it doesn't get put back in the list
Removing an object from the end of a list is cheaper then cycling through the entire list (note removing from the list at list[0] is O(n) , but removing from the list at list[list.count-1] is O(1).
O$$anonymous$$ so maybe it works. And now that you point it out to me it might be faster than searching through the list.
But here is an idea, what if you keep a index number of the object to fire next and just have it go through the list over and over. If the object has not been returned who cares? If you have a thousand bullets out there and one goes missing is anything or anyone going to miss it? And no firing blanks no searching through the list. It might work for a game with a lot of bullets out there all the time. Now I have to make one :)
Answer by Shark-Boy · Aug 10, 2014 at 08:32 PM
So I checked out the tutorial from unity Object Pooling. And I recommend that you watch it if you need to understand more. Mike Geig does a great job of explaining how it works.
OK now for the script. This is in C# and if someone can get a copy in java it would be a good idea.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPoolScript : MonoBehaviour
{
public GameObject pooledObject;
public int pooledAmount = 20;
public bool willGrow = true;
public List<GameObject> pooledObjects;
void Start ()
{
pooledObjects = new List<GameObject>();
for(int i = 0; i < pooledAmount; i++)
{
GameObject obj = (GameObject)Instantiate(pooledObject);
obj.SetActive(false);
pooledObjects.Add(obj);
}
}
public GameObject GetPooledObject()
{
for(int i = 0; i< pooledObjects.Count; i++)
{
if(pooledObjects[i] == null)
{
GameObject obj = (GameObject)Instantiate(pooledObject);
obj.SetActive(false);
pooledObjects[i] = obj;
return pooledObjects[i];
}
if(!pooledObjects[i].activeInHierarchy)
{
return pooledObjects[i];
}
}
if (willGrow)
{
GameObject obj = (GameObject)Instantiate(pooledObject);
pooledObjects.Add(obj);
return obj;
}
return null;
}
}
So to use this script use some code like this
ObjectPoolScript objectPoolScript;
And in the Start method set it to
GetComponent<ObjectPoolScript> ();
and then to fire a bullet (which is what I needed it for) do something like
void Fire()
{
GameObject obj = NewObjectPoolerScript.current.GetPooledObject();
if(obj == null) return;
bullets[i].transform.position = transform.position;
bullets[i].transform.rotation = transform.rotation;
bullets[i].SetActive(true);
}
Anything else you want to do is up to you. Like I said this is supposed to be a script that you can modify and add to. Oh and I did test this and it works well. And if you have a lot of things that need use the same GameObjects you can set it up so that everything that is in the scene can access the script you should watch the video at the link above.(it's in the last half that he builds the generic script and sets it up) And this really is not my script I just did a little edit so that I could attach it to my weapon object. Copy and Paste the code modify it if you need to and make a great game.
Thank you. I modified the code a bit. I don't think the above ever hits the null in the loop. I added a pool max ins$$anonymous$$d.
public class GameObjectPool
{
private int maxObjects;
private GameObject pooledObject;
private List<GameObject> pooledObjects = new List<GameObject>();
public GameObjectPool(GameObject pooledObject, int maxObjects = 500)
{
this.pooledObject = pooledObject;
this.maxObjects = maxObjects;
destroyAll(pooledObjects);
}
public GameObject GetPooledObject(Vector3 position)
{
for (int i = 0; i < pooledObjects.Count; i++)
{
// check active & return inaccive
if (!pooledObjects[i].activeInHierarchy)
{
pooledObjects[i].SetActive(true);
pooledObjects[i].transform.position = position;
return pooledObjects[i];
}
}
// Put a cap on how many we can have
if (pooledObjects.Count < maxObjects)
{
GameObject obj = (GameObject)GameObject.Instantiate(pooledObject, position, Quaternion.identity);
obj.SetActive(true);
pooledObjects.Add(obj);
return obj;
}
return null;
}
private void destroyAll(List<GameObject> objects)
{
foreach (GameObject ob in objects)
{
GameObject.Destroy(ob);
}
objects.Clear();
}
}
Answer by Kiwasi · Aug 10, 2014 at 09:41 PM
The Unity tutorial is great.
I also have a blog post here that works on a slightly different principle
It looks O$$anonymous$$ to me except one thing. You are using SetActive(true) before you pass the object to whatever script is trying to access it. This might cause problems depending on what the script is doing. You should set the position and/or rotation and whatever else you are doing before you activate it. (or so I've been told)
Good point. I might make a note of that in the comments. It was a design choice to do it this way, mainly to avoid the need to call SetActive(true) explicitly in the calling script. If you had complex things happening in OnEnable you might prefer to call SetActive(true). But its one more line to remember every time you use the pool.
Its also worth noting the optimisation in the comments too, haven't put it into the script yet. Removing the last object from a list is dramatically faster then removing the first.
I've also used the same concept for more complex object pools. I have one pool that runs a genetic algorithm across a set of pooled neural nets before returning them. But that's a story for another day.
Answer by Johat · Aug 11, 2014 at 11:52 AM
The other answers here pretty much cover it (definitely worth going through!), but there is this implementation here. I've not used it myself, but it seems legit enough.
It's not too tough to implement yourself though, and the other answers tell you pretty much everything you'd need to know for that =).
the site has shutdown, you can find the library on https://github.com/UnityPatterns/ObjectPool
Johat "this implementation here" link takes to to an ad. there is also a bot trap. he is a scammer don't click his link
Follow this Question
Related Questions
Could I get an explanation of object pooling and how to do it? 2 Answers
How do I set up object pooling in a 2d endless runner? (New to unity) 0 Answers
move pooled object on collision/trigger but keep pooling it 1 Answer
Object pooling for many different Prefabs 2 Answers
Null Reference Exception anytime scene is reloaded? 1 Answer