Question
How can I add and subtract to a variable from multiple game objects without losing the accuracy?
I have more than 100(close to 200) enemy game objects in my scene and 5-6 being spawned every second. I'm using object pooling and the objects are not being instantiated every time but only when needed. I'm trying to record the stats where I can show total enemies remaining and total enemies taken down. A simple mathematical function of addition and subtraction from respective game objects is not adding up to what it should be. For example: Total enemies spawned 200 (when I didn't kill a single one) I kill a lot of enemies in an instant but when I'm done killing them all, enemies remaining is not always zero.
I tried killing the enemies one by one as they spawn and the addition and subtraction adds up correctly.
So how can I add and subtract to a variable from multiple game objects without loosing the accuracy?
public void TookDownEnemy(int enemiesTookDown)
{
//enemiesAlive -= enemiesTookDown;
enemiesTakenDown += enemiesTookDown;
Debug.Log("stats, enemies took down: " + enemiesTakenDown);
UpdateStats();
}
public void SpawnedNewEnemy(int spawned)
{
enemiesAlive += spawned;
UpdateStats();
}
public void UpdateStats()
{
enemiesTakenDownText.text = ": " + enemiesTakenDown.ToString();
enemiesAliveText.text = ": " + (enemiesAlive - enemiesTakenDown).ToString();
}
I'm calling SpawnedNewEnemy from a an enemy spawning game object everytime it spawns a new enemy, TookDownEnemy gets called from the gameobject when they are spawned.
public void InstantiateNewEnemy()
{
StatsManager.Instance.SpawnedNewEnemy(1);
Enemy instance = ObjectPooler.DequeueObject<Enemy>("Enemy");
instance.Initialize(10.0f); // get this hp value from the experience manager
instance.SetThisAlive();
instance.gameObject.SetActive(true);
instance.transform.SetParent(enemiesHolder);
int randomIndex = Random.Range(0, enemySpawnPoints.childCount);
instance.transform.position = enemySpawnPoints.GetChild(randomIndex).position;
instance.transform.rotation = Quaternion.identity;
}
In a similar way when enemy is killed or dies
if(hp <= 0 && !isDead)
{
//Destroy(this.gameObject); // use pooling here
isDead = true;
StatsManager.Instance.TookDownEnemy(1);
this.GetComponent<Animator>().Play("playDead");
Invoke("EnqueueGameObject", 0.25f);
}
Instead of directly adding and subtracting from a variable I made three different variables.
- enemiesSpawned
- enemiesTookDown
- enemiesRemaining
where enemiesRemaining = enemiesSpawned - enemiesTookDown
Even this is having a discrepancy. I'm assuming there should be a way to queue the addition and subtraction operation rather than just doing it.
UPDATE: I tried doing it by queuing the addition and subtraction operations and execute those operations at a defined interval.
public void TookDownEnemy(int enemiesTookDown)
{
enemiesTookDownQueue.Enqueue(enemiesTookDown);
}
public void SpawnedNewEnemy(int spawned)
{
enemiesAliveQueue.Enqueue(spawned);
}
Now I've also limited the spawning of enemies to 260(based on time I'm spawning a total of 260 enemies). When using Queue to add and subtract I'm sumhow(pun intended) always ending up with a difference of 80. Where 80 enemies remaining and I took down 180.
Here's how I'm adding those numbers up every 2 second.
public void UpdateStats()
{
while(enemiesAliveQueue.Count > 0)
{
enemiesAlive += (int)enemiesAliveQueue.Dequeue();
}
while(enemiesTookDownQueue.Count > 0)
{
enemiesTakenDown += (int)enemiesTookDownQueue.Dequeue();
}
enemiesTakenDownText.text = ": " + enemiesTakenDown.ToString();
coinsCollectedText.text = ": " + coinsCollected.ToString();
enemiesAliveText.text = ": " + (enemiesAlive - enemiesTakenDown).ToString();
}