Keeping track of items in a pool?

Prefab
|----GameObject A
| |-----Script aaa
|----GameObject B

And There are some variables such as ID in script aaa.
After clone lots of this prefab like:

for(int i=0;i<10;i++){
GameObject tmp =(GameObject)GameObject.Instantiate(Prefab,Position,Rotation);}

How can i set ID to different numbers?
Thanks

Please note!

This popular answer is

#incredibly old!!

While it is not wrong, it is very out of date. (Remember “unityscript”?!)

One overwhelming point is that these days in Unity you very often plain do not need to use / should not use pooling. It’s a complicated issue and hard to get right.

If you are a new hobbyist programmer and just learning Unity, here is an introduction to what the hell pooling is. But proceed with caution. You can ask somewhere like gamedev.com for opinions on your particular case, whether you actually need pooling or not.

Very often when you think you need pooling, you’re actually just doing something totally the wrong way. So, it’s tricky - take care!


This is a fantastic question because, it’s something you have to do pretty much every single time you use a game engine for any reason.

Indeed, “handling a pool” of gameObjects is so common I reckon one day Unity will add a little system for it.

In all video games you have “pools” of objects, for example fish, bullets, clouds, enemies, whatever it may be. You might have, for example, 40 bullets on standby off screen. When someone uses a machine gun, you use the bullets in order.

Many developers or companies have their own little system they use to generalise this, or, you might just have some typical code you modify each time for each little pool.

Note, if you are not a native English speaker,
in the code below by “model” I mean model as in Claudia Schiffer, not model as in Maya.
It has nothing to do with mesh models, it just means
the “example” version of that thing.
So here we have a pool of enemies:

You’d have a gameObject named “enemies”
which holds all the enemies. It would have a script attached to it
which handles the enemies. That script would load the pool.
(The actual code is below.)

Now, under the “enemies” gameObject, you’d have
at editing time just the one “model enemy”, your one perfect enemy.

To repeat: at development time, before you hit “Play” in the editor. You’ll have one object called enemies. And under that you’ll have just the one object, being your one perfect model enemy.

Later, all the enemies in the pool will be copies of that one perfect enemy!
You will be able to clearly see this in the Hierarchy when you launch it. Suddenly there will be a big string of enemies (all tidily named) under that “folder”. The set-up code will make the pool of enemies,
in this case 25 of them.

(In the example, the developers must have assumed there is never a need for more than 25
enemies on screen at the one time, in this particular game. It could be you only need 10, it could be you need 50 - it depends on the specific situation.)

Now what zhuchun asks is the critical question, how to refer to them?

The model enemy is going to have some sort of script attached to it.
(Very likely, more than one script, but there will be one master script.) That script will be called “Enemy”.

In fact, you need to keep a List of those references … to repeat, you most typically keep a list of links to the scripts themselves … not to, say, the Transforms.

So like this,

#How to do?
.

#pragma strict

private var modelEnemy:enemy;
private var ee:List.<enemy>;
private var eeKount:int;

function Awake()
  {
  _loadPool();
  // note, sometimes better to do this in Start()
  // reason is beyond scope of current discussion
  }

function _loadPool()
  {
  modelEnemy = FindUnderHereNamed("modelEnemy").GetComponent(enemy);
  
  // again note that there is one "model enemy" sitting under us
  // and indeed it will have a script "enemy" on it
  // that's the general purpose script that drives the enemy.
  
  modelEnemy.transform.position = offscreenHoldingArea;
  // we'll just leave our model sitting out of the way !
  
  ee = new List.<enemy>();
  
  // again note we're making a list OF THE SCRIPTS,
  // the script itself is the thing you keep, almost always,
  // not the transform or the gameObject
  
  for ( var c:int=0; c<25; ++c )
    {
    var newy:GameObject = Instantiate( modelEnemy.gameObject );
    // see note 1
    
    newy.transform.parent = transform;
    
    newy.transform.localPosition.z += 0.1*c;
    // see note 2
    
    newy.name = "ee" + c;
    // always give them a name so it makes sense in your editor
    
    ee.Add( newy.GetComponent(enemy) );
    // and that's how to build the "ee" List of the scripts
    }
  
  eeKount = ee.Count;
  // it's all that easy, thank goodness
  }
  
  // note 1
  // it is extremely important that the thingies,
  // "enemy" in this example, LOOK AFTER THEMSELVES.
  // for example you might think here, oh, why isn't he
  // marking them inactive, colouring them yellow, etc.
  // in fact you should do all that IN the "enemy" script
  // when it creates itself
  
  // note 2
  // that is a fun line of code
  // it simply MAKES MORE UNDERSTANDABLE in the editor
  // what the hell is happening with your offscreen pool
  // delete it if you have no sense of humour

#How to use?
.

Now that you’ve done all that it’s very easy to refer to the various "enemy"s.

function makeKickAssEnemyHere(
            rightHereBaby:Vector3, AWESOMENESS:notBad )
  {
  // which one will we use from our pool?
  // keep that in a variable "current"
  // notice we use eeKount from above.
  ++current;
  if ( current >= eeKount ) current = 0;
  
  ee[current].getReady();
  ee[current].transform.position = rightHereBaby;
  
  ee[current].setEffects( notBad );
  
  ee[current].fireworksCount( Random.Range(5,9) );
  
  // you can see that ee[current] gets you to the enemy
  // don't forget ee[current].transform is also there for you
  }

ee[hasBeenDestroyed].getReallyAngry();
ee*.goOffscreen();* 

ee*.danceLikeDevil( 5.0 );*

function endlessCrazedAttack()
{
makeKickAssEnemyHere(somewhere(),AWESOMENESS.moderate);
Invoke(“endlessCrazedAttack”, 5.0);
}

// very often you have to cycle through all the active "enemy"s

function distanceToNearestOnscreenEnemyFromPoint( pp:Vector3 ):float
{
// … example code …

for ( var i:int=0; i<eeKount; ++i )
{
if ( ee*.active )*
{
onePosition = ee*.transform.position;*
// or perhaps …
onePosition = ee*.positionOfMyGrapplingHook();*
oneDistance = ( onePos - pp ).sqrMagnitude;

// … find biggest …
}
}
return biggestDistanceFound;
}
So, enjoy.
Like I say, people often make a whole subsystem to generalize
this sort of pooling concept.
But really as a pedagogical matter there’s a lot to be said
for just doing it manually each time.
It’s trivial so it’s not like you are encapsulating so much anyway,
and it’s the sort of thing that tends to be
“a little different each time”
so I suggest for now just go ahead and do it individually
for each enemy, bullet, cloud, whatever.
Note that quite often you wanna keep TWO (or more)
such Lists, side by side.
Say you have another script on the enemy, “enemyOptions”.
You can just get to it like this
ee[42].GetComponent[enemyOptions].blowStuffUp()
but everyone hates using GetComponent.
So you may well want to have two Lists, just build them
both as you go.
Often too you also want a List with the transforms,
just for tidyness really,
if you really also use the transform a lot.
(In a sense, you “shouldn’t be” using the transform
a lot at this level, you should let enemy itself
do all the work.)
Just FYI inevitably and conversely in each “enemy”
script you usually need a variable “myBoss”
which takes you back to the “enemies” level script.
Very often, each individual enemy needs to know
it’s own “number” as seen by the enemies script.
If so, just pass it down, near “note 2” in the
pool loader.
Here’s the core idea again with no fluff
private var modelEnemy:enemy;
private var ee:List.;
private var eeKount:int;
for ( var c:int=0; c<25; ++c )
{
var newy:GameObject = Instantiate( modelEnemy.gameObject );
newy.transform.parent = transform;
newy.name = “ee” + c;
ee.Add( newy.GetComponent(enemy) );
}
eeKount = ee.Count;
The most critical thing in all this is, never, ever ever use an apostrophe when using
a plural. If you want the plural of a script called enemy, type enemys which is utterly correct, or "enemy"s. Never, ever ever use an apostrophe.

Just wanted to add that queues are more effective for Pools than Lists. Simply because you can enqueue / dequeue without making copies in memory, which flags the garbage collector - which’s exactly what you want to avoid with pools. If you don’t “remove” items from a single list you’ll have to loop over it to find “available” items - also not effective if you have a huge pool. You can avoid it all together using two queues, one for available and other for in-use pool items.

I wonder why people don’t use them more often for pool systems.

using UnityEngine;
using System.Collections;

public class BrickScript : MonoBehaviour {

int bulltNo;
public GameObject[] objBullt;
public AudioSource shoot;
public FrisBullet[] bullt;
int a;
float Cooler;

//bool cooldown;

// Use this for initialization
void Start () {

	//Declare an array of an invariable number
	bulltNo = GameObject.FindGameObjectsWithTag ("Bullet").Length;
	objBullt = new GameObject[bulltNo];
	bullt = new FrisBullet[bulltNo];

	objBullt = GameObject.FindGameObjectsWithTag ("Bullet");

	//specific amount of loops
	for(int i = 0;i<bulltNo;i++){

		bullt _= objBullt*.GetComponent<FrisBullet>();*_

* }*
* a = 0;*
}

* // Update is called once per frame*
* void Update () {*
_ transform.Rotate (new Vector3 (0, 50 * Input.GetAxis (“Horizontal”) * Time.deltaTime, 0));_
* if(Input.GetMouseButton(0))*
* {*
* bullt[a].StartCoroutine(“Fritter”);*
* a++;*
* if(a >= bulltNo) a = 0;*

* }*
* if (Input.GetMouseButtonUp (0))*
* shoot.Stop ();*
* if (Input.GetMouseButtonDown (0))*
* shoot.Play ();*

* }*
}
--------------------------------------------------
Attatch the Above Script to your Character
Attatch the below script to your projectile weapon
--------------------------------------------------
using UnityEngine;
using System.Collections;
public class FrisBullet : MonoBehaviour {
* public float time;*

* Transform firelocke;*
* // Use this for initialization*
* void Start () {*
* firelocke = GameObject.FindGameObjectWithTag (“Nuzz”).GetComponent ();*
* }*

* // Update is called once per frame*
* void Update () {*

* }*
* IEnumerator Fritter(){*
* time = 0;*
* transform.position = firelocke.position;*
* transform.rotation = firelocke.rotation;*
* while (time < 2){*
_ transform.Translate(new Vector3 (0, 0, 20 * Time.deltaTime));_
* time += Time.deltaTime;*
* yield return null;*
* }*
* transform.position = new Vector3 (0,100,0);*
* }*
}