Let's say I have two scripts:
- SpawnManager
- Enemy
In SpawnManager
, I have the function SpawnEnemyWave
that should instantiate 3 enemies, if the random number generator is lower than 5, then one of them should have a higher movement speed, the other shouldn't move at all.
In SpawnManager
:
bool toughEnemy = true;
int waveNumber = 3;
float randomNumber = Random.Range(0, 10);
void Start()
{
SpawnEnemyWave(waveNumber);
}
void SpawnEnemyWave(int enemiesToSpawn)
{
float randomNumber = Random.Range(0, 10);
print(randomNumber);
for (int i = 0; i < enemiesToSpawn; i++)
{
if ((randomNumber < 5) && toughEnemy)
{
print("Tough");
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
toughEnemy = false; //I make sure there is only one tough enemy per wave
}
else
{
print("Weak");
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
}
}
}
In Enemy
, I'm checking if the toughEnemy
variable is set to true to modify the enemy speed before the instantiation, I put those if statements in the start function because I think than when an enemy is instantiated is when it is called.
void Start()
{
spawnManager = GameObject.Find("Spawn Manager").GetComponent<SpawnManager>();
if (spawnManager.toughEnemy)
{
speed = 1;
print("Speed " + speed);
}
else
{
speed = 0;
print("Speed " + speed);
}
}
The problem is, when the random number is 0 in the logs i see this...
- random number:0
- Tough (the i in the for loop is 0)
- Weak (the i in the for loop is 1)
- Weak (the i in the for loop is 2)
- speed 0
- speed 0
- speed 0
And what I was expecting was something like below, because I'm modifying the variable in the SpawnManager
script first before instantiating the enemy.
- random number:0
- Tough (the i in the for loop is 0)
- speed 1
- Weak (the i in the for loop is 1)
- speed 0
- Weak (the i in the for loop is 2)
- speed 0
What am I missing here?
Timing. You’re partly correct thinking that
Start
will be called when the object is instantiated. But, it will be called when the next frame starts. In your current loop, you’re setting up the objects to be instantiated, then you set thetoughEnemy
to true. When the next frame starts, all the enemies think that a tough enemy has been set, and the output you see is correct.If you want the manager to control the enemies, I’d personally include something like a
Setup
method, called by the manager. For example, in theEnemy
script:Then, when you instantiate the enemy in your manager, do something like:
Here’s the life cycle of a ‘frame’
Notice that the
Update
method processing occurs about in the middle of the frame lifecycle. You’re Instantiating 3 objects in the same Update method. THEN … the frame ends, and at the beginning of the next frame, theStart
event for each of the new objects is triggered.