Is there a point in recycling value types unity
Yes, some datatypes not all.
does this apply to value type variables (integers, vectors)?
No.
It depends on the variable type.
This does not apply to int
, double
, float
, bool
, Vector3
and Vector2
and other similar datatypes. It does not even apply to string
because already, string
cannot be re-used in C#. strings
are immutable.
In-fact, using int
from a local variable, lets say in a while
loop is faster than using int
declared as global.
*Examples of when you should declare variable once and re-use it or in your own words, recycle or re-use variables in Unity*.
Arrays:
If a function contains array and that function is often called.
void functionCalledVeryOften()
{
float[] playerLives = new float[5]; //This is bad because it allocates memory each time it is called
for (int i = 0; i < playerLives.Length; i++)
{
playerLives[i] = UnityEngine.Random.Range(0f,5f);
}
}
This allocates memory each time and can be solved by making the array global and initializing it outside the function once. You can create a simple function that resets the data in the array into 0.
float[] playerLives = new float[5];
void functionCalledVeryOften()
{
for (int i = 0; i < playerLives.Length; i++)
{
playerLives[i] = UnityEngine.Random.Range(0f,5f);
}
}
Creating new Objects:
Creating new Objects takes resources and can cause problems on mobile devices. This depends on how often you do this.
The code below creates a GameObject (bullet) then attaches Rigidbody
to it and then shoots it.This happens every frame while space bar is held down and finally destroys the bullet 10
seconds later.
void functionCalledVeryOften()
{
if (Input.GetKey(KeyCode.Space))
{
//Create new Bullet each time
GameObject myObject = new GameObject("bullet");
Rigidbody bullet = myObject.AddComponent<Rigidbody>() as Rigidbody;
//Shoot Bullet
bullet.velocity = transform.forward * 50;
Destroy(myObject);
}
}
The code above is bad as it allocates memory each time new GameObject is created and when the GameObject is destroyed, it will also trigger garbage collector. This can slow down and cause hiccups in your game.
The solution to the above code is Object pooling. You can learn more about it here: Object Pooling tutorial from Unity
Example of simple fix for this with a global variable:
List<GameObject> reUsableBullets;
int toUseIndex = 0;
void Start()
{
intitOnce();
}
//Call this function once to create bullets
void intitOnce()
{
reUsableBullets = new List<GameObject>();
//Create 20 bullets then store the reference to a global variable for re-usal
for (int i = 0; i < 20; i++)
{
reUsableBullets[i] = new GameObject("bullet");
reUsableBullets[i].AddComponent<Rigidbody>();
reUsableBullets[i].SetActive(false);
}
}
void functionCalledVeryOften()
{
if (Input.GetKey(KeyCode.Space))
{
//Re-use old bullet
reUsableBullets[toUseIndex].SetActive(true);
Rigidbody tempRgb = reUsableBullets[toUseIndex].GetComponent<Rigidbody>();
tempRgb.velocity = transform.forward * 50;
toUseIndex++;
//reset counter
if (toUseIndex == reUsableBullets.Count - 1)
{
toUseIndex = 0;
}
}
}
So basically, you create an Object inside a function before Game begins, then store the reference in a global variable. You will then re-use that Object you created in the function since its reference is held in a global variable.
Instantiate:
The Instantiate function is used to create of copy of a prefab.
The code below will instantiate a bullet then shoots it every frame while space bar is held down and finally destroys it 10
seconds later.
public GameObject bulletPrefab;
void functionCalledVeryOften()
{
if (Input.GetKey(KeyCode.Space))
{
//Create new Bullet each time
Rigidbody bullet = Instantiate(bulletPrefab, new Vector3(0, 0, 0), Quaternion.identity) as Rigidbody;
//Shoot Bullet
bullet.velocity = transform.forward * 50;
Destroy(myObject,10f);
}
}
The code above is bad as it allocates memory depending on how many components is attached to the bullet prefab and how much child GameObject is under it. The solution is also use Object Pooling. Instantiate the GameObject in a function, store the reference in a global variable then re-use them. The solution is the-same with the solution above.
In conclusion, the example code in your question does not apply this.
You can learn more about Memory Management in Unity here.