How to target a specific GameObject when many are of the same type?

“Unity (C#) How To Destroy/Deactivate one enemy without affecting other enemies of the same type, when jumping on one of their heads.”

Currently I’m only able to have one zombie in my game. When I add another (duplicate or drag from prefab), then run the game, I can squash one enemy but when I try to jump on the second zombie’s head it says “Coroutine couldn’t be started because the game object “Zombie (1)” is inactive”.

Here’s the player’s stompbox script code & below that the ZombieController script code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class StompEnemy : MonoBehaviour {
    
        private Rigidbody2D playerRigidbody;
        public ZombieController zombieController;
    
        public float bounceForce;
        // a bounce force of 12 is wonderful (set in unity's inspector)
    
    	// Use this for initialization
    	void Start () {
            playerRigidbody = transform.parent.GetComponent<Rigidbody2D>();
            zombieController = FindObjectOfType<ZombieController>();
        }
    	
    	// Update is called once per frame
    	void Update () {
    		
    	}
    
        private void OnTriggerEnter2D(Collider2D other)
        {
            if(other.tag == "Zombie")
            {
                zombieController.Stomped();
                playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, bounceForce);
            } 
        }
    
    }

Now here’s the ZombieController script code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZombieController : MonoBehaviour {

    Animator zombieAnimator;
    Rigidbody2D myRigidBody;
    [SerializeField] float moveSpeed = 1f;

    public bool isAlive = true;

    // Use this for initialization
    void Start () {
        zombieAnimator = GetComponent<Animator>();
        myRigidBody = GetComponent<Rigidbody2D>();
    }
	
	// Update is called once per frame
	void Update () {
        if (!isAlive) { return; }
        if (isFacingRight())
        {
            myRigidBody.velocity = new Vector2(moveSpeed, 0f);
        }
        else
        {
            myRigidBody.velocity = new Vector2(-moveSpeed, 0f);
        }
    }

    bool isFacingRight()
    {
        return transform.localScale.x > 0;
        // if it's positive he's facing right, and if negative, facing left.
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        transform.localScale = new Vector2(-(Mathf.Sign(myRigidBody.velocity.x)), 1f);
    }

    public void Stomped()
    {
        isAlive = false;
        transform.localScale = new Vector2(-(Mathf.Sign(myRigidBody.velocity.x)), 1f);
        zombieAnimator.SetBool("Squash", true);
        if (isFacingRight())
        {
            myRigidBody.velocity = new Vector2(Mathf.Epsilon, 0f);
        }
        else if (!isFacingRight())
        {
            myRigidBody.velocity = new Vector2(-Mathf.Epsilon, 0f);
        }
        gameObject.layer = 11;
        StartCoroutine(WaitXSecond());
    }

    public IEnumerator WaitXSecond()
    {
        yield return new WaitForSeconds(2f);
        gameObject.SetActive(false);
        zombieAnimator.SetBool("Squash", false);
    }

}

How do I implement multiple zombies using the same script attached to each one? When I’ve tried having three zombies I’d jump on the first one’s head and another zombie would die (show the squashed animation, then disappear after two seconds) and the remaining zombies would no longer be jump-on-head-able, displaying the coroutine error above.

Any help would be extremely appreciated…

Hi Josh,

I’m about to step out of the door so this is a pretty quick response without a lot of time given to it, but…

I’m guessing their is a ZombieController.cs script component on each zombie?

Assuming so, then this line is a bit of a code-smell…

zombieController = FindObjectOfType<ZombieController>();

Any of the Find methods, apart from not being overly performant, return the first GameObject which matches. From the documentation;

Description

Returns the first active loaded object of Type type .

This could well be why you stomp an enemy and another one dies, because you are not Finding the ZombieController for the zombie you are stomping, just arbitrarily grabbing the first you come to.

If I’m correct with regards to the above, then, you might be able to resolve this by removing that line from the Start method and instead, and dropping the member variable of the same type, as you’re not using it anywhere else. Then within your if statement in the OnTriggerEnter2D method, get the ZombieController component at that point, once you know a) which GameObject you have made contact with and b) that its a zombie… for example;

private void OnTriggerEnter2D(Collider2D other)
{
    if(other.tag == "Zombie")
    {    
        ZombieController zombieController = other.gameObject.GetComponent<ZombieController>();

        zombieController.Stomped();
        playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, bounceForce);
    } 
}

In the above, you are getting a reference to the other GameObject from the collision, e.g. the zombie, then getting its ZombieController component, so you know its the one on the right GameObject.

Sorry for the rushed response, let me know how you get on. :slight_smile:


See also;

Dear Rob,

You are AWESOME. That fixed it. Thank you so much!!!

1 Like

Hey Josh, you’re very welcome, glad you can move forward again and sorry for the rushed message early :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms