- Home /
Checking if first item in array has been destroyed
Hello and thanks for helping. I am making an RTS in which the players units are selected and then I select enemy units for them to destory. The enemy units get placed in an array called updateEnemyList. Each player unit has a function called Attack() which then sorts the list to put the closest enemy in updateEnemyList[0], and then attacks the first GameObject in the Listarray (which is the closest one).
I am running into an issue where one the first enemy in the ListArray is killed, I cannot have the player unit find the next enemy in the list. The enemy is killed through a Destroy(gameObject) script attached as a component to the enemy. I have attempted the following method to get the next closest enemy, though it does not work. Units simply go idle once the first enemy is killed.
// Update is called once per frame
void Update ()
{
if (updateEnemyList.Count > 0 && updateEnemyList [0] == null)
Attack (updateEnemyList);
}
Does anyone have a better way to determine if updateEnemyList [0] has been destroyed by other scripts?
Thanks.
Answer by koblavi · Jun 03, 2015 at 02:04 AM
if (updateEnemyList.Count > 0 && updateEnemyList [0] == null)
The above check will always return false if it's done in the same update loop cycle (Not necessarily the same script) as the element is destroyed because when an object is destroyed, its reference is not to null immediately. Rather it is done just before rendering the corresponding frame.
Here is a snippet to test out the behaviour:
void Start () {
StartCoroutine(CreateAndDestroy());
}
IEnumerator CreateAndDestroy(){
//create
print("Creating Clone");
clone = Instantiate<Transform>(obj);
yield return new WaitForSeconds(2);
//destroy
print("Destroying Clone");
Destroy(clone.gameObject);
//Cheking immediately for null (should return false)
print("Checking null");
print(clone==null);
yield return null;
//wait till next frame and check again
print("Checking null on next frame (should return true)");
print(clone==null);
}
One possible solution will be to delay your null check till the next frame.
Another solution (which I personally think could be simpler if I think through a bit more) is detailed below:
Create a custom behaviour which extends the MonoBehavior class and add a custom Destroy method and an isDestroyed field which is set immediately after Destroy executes.
Let all your subsequent behaviors extend that class and call the custom destroy method to destroy other Behaviors that extend custom Bevahior.
check IsDestroyed property (instead of a null check) to query if an object has been destroyed.
Code snippets for classes are below:
Custom base behavior classs:
public class MyBehavior : MonoBehaviour
{
// Property to check after calling Destroy
private bool _isDestroyed = false;
public bool IsDestroyed{ get {
return _isDestroyed;
}
}
//custom Destroy
public static void Destroy(MyBehavior obj, bool destoryGameObject = false){
if(destoryGameObject){
Destroy(obj.gameObject);
}
else{
Destroy(obj);
}
obj._isDestroyed = true;
}
}
Object that extends custom Behaviour:
public class DestroyableObject : MyBehavior {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Instantiating and Destroying our Object (Similar to previous example but replaces null check with isDestroyed() ):
IEnumerator CreateAndDestroy(){
//create
print("Creating Clone");
clone = Instantiate<DestroyableObject>(obj);
yield return new WaitForSeconds(2);
//destroy
print("Destroying Clone");
Destroy(clone,true);
//Cheking immediately for IsDestroyed (should return true)
print("Checking IsDestroyed");
print(clone.IsDestroyed);
yield return null;
//wait till next frame and check again
print("Checking null on next frame");
print(clone==null);
}
Hope this helps
Wow thank you. To be honest, I am new to Unity and would struggle implmenting this well. Right before you posted this I found an alternative, but somewhat similiar method. Ins$$anonymous$$d of destroying enemies when they died, I turned them off. Then in my player script I had functions to check for enemies in the list that had been turned off and removed them from the ArrayList.
However, I thank you for all of the hard work you put into helping me. I really appreciate it.