- Home /
destroying a unit and removing it from a list
Hey guys, Im making a simple rts game and when I have my player unit destroy an enemy unit is keeps returning erros and breaks the game. I do not know the right way to go about this. I have lists detect the enemies on the field. The player unit finds the closest one and attacks it. WHen its dead i use destroy object and some null exceptions but im still getting errors. Could you help? Thanks,
public void Start () {
StartCoroutine (CountEnemies()); //counts the amount of enemies that have been spawned
StartCoroutine (DetectEnemies()); //this detects if the enemies are in range, and then moves to them
}
public void FixedUpdate () { //runs update at a fixed fps
//attacking the enemy
if (playerAttacking == true) {
GameObject EnemyObject = EnemyList[minDistanceIndex]; //creates an object for that specific player unit
if(EnemyObject != null){
Enemy EnemyHealthDecrease = EnemyObject.GetComponent<Enemy> ();
// print (Time.time);
if(Time.time>=coolDown){
Debug.Log ("-----------------------the player hit an enemy unit!");//simple test for enemy attack
if(EnemyHealthDecrease.health>0){
EnemyHealthDecrease.health-=30;
print("the units health is at" + EnemyHealthDecrease.health);
coolDown = Time.time + attackRate;
}
if(EnemyHealthDecrease.health<=0){
Destroy(EnemyObject);
EnemyList.RemoveAt(minDistanceIndex);
playerAttacking=false;
DistanceToEnemyList.Clear();
SortedDistanceToEnemyList.Clear();
}
}
}
}
IEnumerator CountEnemies(){ //this is where the game detects the # enemies that have been spawned
while (true) {
GameObject[] EnemyArray = GameObject.FindGameObjectsWithTag("Enemy"); //creates an array populated with the enemies
for(int i=0 ; i<EnemyArray.Length; i++){ //iterates through the array and adds all objects to the list
if(EnemyArray[i]!=null){
EnemyList.Insert(i, EnemyArray[i]); //adding to the list
}
}
yield return new WaitForSeconds(1f);
}
}
IEnumerator DetectEnemies(){
while (true) {
if(playerAttacking==false){
for(int i=0; i< EnemyList.Count; i++){
if(EnemyList[i] !=null){
float distance = Vector3.Distance (transform.position, EnemyList[i].transform.position); //finds distance between enemy and player
DistanceToEnemyList.Insert(i,distance); //inserts the distance values at the indicies
SortedDistanceToEnemyList.Insert(i,distance); //this is the same as distancelist but will be sorted
SortedDistanceToEnemyList.Sort();//sorts the list in ascending order
//min distance is the first index of sorted list...
}
}
if(SortedDistanceToEnemyList[0]!=null){
minDistanceIndex = DistanceToEnemyList.IndexOf(SortedDistanceToEnemyList[0]);
}
}
//this should give the index of the smallest distance
if (DistanceToEnemyList[minDistanceIndex] <= 10 && minDistanceIndex!=null) { //if the distance is less than 10 between player unit and enemy unit
//index out of range?
GameObject enemyObject = EnemyList[minDistanceIndex]; //creates an object for that specific player unit
if(enemyObject!=null){
AstarAIEnemy enemyObjectDetection = enemyObject.GetComponent<AstarAIEnemy> (); //gets astarai code for that unit
targetPosition = enemyObjectDetection.transform.position; //sets the enemy position to the pos of the player unit
float distanceToTargetPos = Vector3.Distance (targetPosition, transform.position); //finds distance between the two units
if (distanceToTargetPos > 2 && distanceToTargetPos<=10) {
playerAttacking=false;//this makes it so the enemy stops attacking when player is far away
seeker.StartPath (transform.position, targetPosition, OnPathComplete); //if distance is more than 3 than travel towards its destination
}
if (distanceToTargetPos<2){
playerAttacking=true;
}
}
}//end of if distance < X
// Debug.Log("Check Enemy detection");
//DistanceToEnemyList.Clear();
//SortedDistanceToEnemyList.Clear();
yield return new WaitForSeconds(1f);
}
}
So which line in this code are the null references co$$anonymous$$g from? P.S. you shouldn't call SortedDistanceToEnemyList.Sort();
inside the for loop. It's a heavy call and the result is the same IF you sort it once after the loop.
@Nose$$anonymous$$ills It is co$$anonymous$$g from everywhere I have put a if(X !=null) statement. See the comment below that I left to Shadowys for more information. Thanks for looking!
Answer by camtronius · Jun 10, 2014 at 05:14 PM
I figured it out. Basically when an object was destroyed, it was removed from the game so the EnemyArray wasnt detecting it anymore. It was still in the other lists though. I just made it so the other lists are cleared when the enemy is destroyed, and moved around some playerAttacking bools. Thanks for your help,
Answer by Shadowys · Jun 09, 2014 at 07:38 AM
What's the bug that you have encountered? like killing an enemy doesn't kill it, or it spawns more, or the enemy respawns? I would have moved the destroying code to the enemy(die when life<0) though, since the enemy array is automatically updated each frame, so the player don't have to do focus on how the enemy dies.
@Shadowys the problem is that I am getting "array index out of bounds" errors and another that is saying "object is still trying to be referenced after it is deleted ...". Basically everywhere I have put a if(X !=null){} is where the errors have been appearing. I think the problem is once the enemy is deleted, it still exists in the list even though i deleted it. Im sure its a simple fix somewhere in my code. Thanks,
@Shadowys Also, I already have the destroying code when enemy health<0 dont I?
if(EnemyHealthDecrease.health<=0){ //check if enemy health <0
Destroy(EnemyObject); //enemy is destroyed then
EnemyList.RemoveAt($$anonymous$$DistanceIndex);
playerAttacking=false;
DistanceToEnemyList.Clear();
SortedDistanceToEnemyList.Clear();
}