Survival shooter enemies wont take damage

I’m doing the survival shooter tutorial for unity and I just added the script which makes the enemies take damage from the players gun. I added the script to the enemy but whenever I play it they dont take damage

using UnityEngine;

public class EnemyDamage : MonoBehaviour
{
    public int startingHealth = 100;           // The amount of health the enemy starts the game with.
    public int currentHealth;                  // The current health the enemy has.
    public float sinkSpeed = 2.5f;             // The speed at which the enemy sinks through the floor when dead.
    public int scoreValue = 10;                // The amount added to the player's score when the enemy dies.
    public AudioClip deathClip;                // The sound to play when the enemy dies.


    Animator anim;                             // Reference to the animator.
    AudioSource enemyAudio;                    // Reference to the audio source.
    ParticleSystem hitParticles;               // Reference to the particle system that plays when the enemy is damaged.
    CapsuleCollider capsuleCollider;           // Reference to the capsule collider.
    bool isDead;                               // Whether the enemy is dead.
    bool isSinking;                            // Whether the enemy has started sinking through the floor.


    void Awake()
    {
        // Setting up the references.
        anim = GetComponent<Animator>();
        enemyAudio = GetComponent<AudioSource>();
        hitParticles = GetComponentInChildren<ParticleSystem>();
        capsuleCollider = GetComponent<CapsuleCollider>();

        // Setting the current health when the enemy first spawns.
        currentHealth = startingHealth;
    }

    void Update()
    {
        // If the enemy should be sinking...
        if (isSinking)
        {
            // ... move the enemy down by the sinkSpeed per second.
            transform.Translate(-Vector3.up * sinkSpeed * Time.deltaTime);
        }
    }


    public void TakeDamage(int amount, Vector3 hitPoint)
    {
        // If the enemy is dead...
        if (isDead)
            // ... no need to take damage so exit the function.
            return;

        // Play the hurt sound effect.
        enemyAudio.Play();

        // Reduce the current health by the amount of damage sustained.
        currentHealth -= amount;

        // Set the position of the particle system to where the hit was sustained.
        hitParticles.transform.position = hitPoint;

        // And play the particles.
        hitParticles.Play();

        // If the current health is less than or equal to zero...
        if (currentHealth <= 0)
        {
            // ... the enemy is dead.
            Death();
        }
    }


    void Death()
    {
        // The enemy is dead.
        isDead = true;

        // Turn the collider into a trigger so shots can pass through it.
        capsuleCollider.isTrigger = true;

        // Tell the animator that the enemy is dead.
        anim.SetTrigger("Dead");

        // Change the audio clip of the audio source to the death clip and play it (this will stop the hurt clip playing).
        enemyAudio.clip = deathClip;
        enemyAudio.Play();
    }


    public void StartSinking()
    {
        // Find and disable the Nav Mesh Agent.
        GetComponent<NavMeshAgent>().enabled = false;

        // Find the rigidbody component and make it kinematic (since we use Translate to sink the enemy).
        GetComponent<Rigidbody>().isKinematic = true;

        // The enemy should no sink.
        isSinking = true;

        // Increase the score by the enemy's score value.
        ScoreManager.score += scoreValue;

        // After 2 seconds destory the enemy.
        Destroy(gameObject, 2f);
    }
}

The 2 errors are

Assets/EnemyDamage.cs(91,22): error CS0246: The type or namespace name NavMeshAgent’ could not be found. Are you missingUnityEngine.AI’ using directive?

Assets/EnemyDamage.cs(91,38): error CS1061: Type T’ does not contain a definition forenabled’ and no extension method enabled’ of typeT’ could be found. Are you missing an assembly reference?

I’ve looked for answers but no one seems to be having the same problem.

EDIT

I added

using UnityEngine.AI;

and now it dosent give me errors, but they wont take damage. No clue what to do

You will need to find out (a) is the TakeDamage method actually being called and (b) if so, what is it doing.

There are 2 main ways to go about this - (1) use a debugger , e.g. in Visual Studio or (2) add Debug.Log statements into the method.

I added Debug.Log on line 55 in the TakeDamage function and when i play tested and hit the enemy it never showed up in the console.

Heres the player shooting script, the enemy is also on the layer “shootable”

using UnityEngine;

public class PlayerShooting : MonoBehaviour


{
    public int damagePerShot = 20;
    public float timeBetweenBullets = 0.15f;
    public float range = 100f;
    public float ammo = 30;
    public float reload = 0;

   



    float timer;
    Ray shootRay = new Ray();
    RaycastHit shootHit;
    int shootableMask;
    ParticleSystem gunParticles;
    LineRenderer gunLine;
    AudioSource gunAudio;
    Light gunLight;
    float effectsDisplayTime = 0.2f;

   


    void Awake ()
    {
        shootableMask = LayerMask.GetMask ("Shootable");
        gunParticles = GetComponent<ParticleSystem> ();
        gunLine = GetComponent <LineRenderer> ();
        gunAudio = GetComponent<AudioSource> ();
        gunLight = GetComponent<Light> ();
       
    }


    void Update ()
    {
        timer += Time.deltaTime;

        if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0)
        {
           
            Shoot ();
            ammo = ammo - 1;
            print(ammo + " ammo");
        }

        if(timer >= timeBetweenBullets * effectsDisplayTime)
        {
            DisableEffects ();
           
        }

       
       
    }

   

   

    public void DisableEffects ()
    {
        gunLine.enabled = false;
        gunLight.enabled = false;
    }


    void Shoot ()
    {
        timer = 0f;

        gunAudio.Play ();

        gunLight.enabled = true;

        gunParticles.Stop ();
        gunParticles.Play ();

        gunLine.enabled = true;
        gunLine.SetPosition (0, transform.position);

        shootRay.origin = transform.position;
        shootRay.direction = transform.forward;

        if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
        {
            EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
            if(enemyHealth != null)
            {
                enemyHealth.TakeDamage (damagePerShot, shootHit.point);
            }
            gunLine.SetPosition (1, shootHit.point);
        }
        else
        {
            gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
        }
    }
}

Have you added Debug.Log lines in Shoot()? Or even better- debugged it through? Does it get called?

If so, Does the code inside the if on line 93 get reached?

If so, does line 96 get executed?

right below EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> (); I added Debug.Log(“shot”); and it got printed. But right below enemyHealth.TakeDamage (damagePerShot, shootHit.point); I added another Debug.Log and it didnt print once.

And what do you conclude from that? Hint: have you tried checking the value of enemyHealth at line 94?

That mabye their health value isnt being found?

That would seem a reasonable guess. Have you checked to see if that is the case?

Can you just tell me what to do if you know, I know youre trying to get me to solve my problems but this is for a school project and I’ve been trying to fix this single issue for 2 weeks.

It’s not so much a case of me knowing- I cannot be 100% sure as I do not have access to your entire project and setup. Also, do bear in mind that this is not the only issue you are going to face with this software project or any other. As soon as this problem is resolved, you will simply move onto the next one (whatever that may be).

As you correctly observe, that is why I am trying to get you to consider how you approach these problems. I appreciate that it isn’t always fun when you get stuck on something for ages however.

Ok, we know that the ray cast has definitely hit an object. However, if enemyHealth is, as we suspect, indeed null then that will mean there is no such component directly on that object.

So now you need to determine (a) exactly what object has the raycast hit and (b) does that object definitely have an EnemyHealth component on it (or is it instead on a parent or child object, for example, or even was it removed by some other function somewhere during runtime?).

To do this, I would make a suggestion to you, try doing this:

  • Create a new scene.
  • To that scene add only one player gun and one enemy. Set the gun within range of, and pointing at, the enemy.
  • Now you know the gun must hit only the enemy and no other objects. You also know whether the enemy has an EnemyHealth component attached.
  • Fire the gun.
  • Did the enemy take damage (i.e. did your Debug.Log statement work)?
  • If it did, then the problem is somewhere within your main game scene. If it did not, then the problem is likely with the enemy object (e.g. check the component is not on a parent/ child object).

One other thing, are you able to download the community edition of Visual Studio (it’s free)? Honestly, if you are able to become comfortable using the debugger you will be amazed at how helpful that is to be able to dynamically see what is happening inside your code at runtime.

Sorry for the really long response time, I created the scene and followed what you told me to do, I checked the Debug.Log statements and they should work if it would’ve taken damage which it didnt. The enemies are not part of a parent and each individual one has its own slot in the Hierarchy. Edit - I also just playtested and realized that now my character isnt taking damage either, this has never happened before

Ok, so let’s now try this:

  • In your test scene, add a cube (primitive). Not near your test enemy.
  • To the cube, add only a RigidBody.
  • Create the script below and place it on your gun object.

Now, when the gun faces the cube, do you see both debug lines printed out?

I am going to assume here the answer is yes (because that is what I see happening). So, now try adding your EnemyHealth component to the cube. In the script below (line 19), change both RigidBody to be EnemyHealth and rerun the test.

Do you still see the 2 debug lines displayed?

public class Test : MonoBehaviour
{
    IEnumerator Start()
    {
        WaitForSeconds waitOneSec = new WaitForSeconds(1f);

        while (true)
        {
            yield return waitOneSec;

            RaycastHit shootHit;
            myShootRay.origin = transform.position;
            myShootRay.direction = transform.forward;
            Debug.DrawRay(myShootRay.origin, transform.forward * range, Color.white, 1f);

            if (Physics.Raycast(myShootRay, out shootHit, range))
            {
                Debug.Log("Ray has hit an object");
                Rigidbody enemyHealth = shootHit.collider.GetComponent<Rigidbody>();

                if (enemyHealth != null)
                {
                    Debug.Log("Target object has the requested component");
                }
            }
        }
    }

    [SerializeField] [Range(0.5f, 20f)] int range = 3;
    Ray myShootRay = new Ray();
}

I just fixed it, I just copied the script from the online and pasted it and now it works fine, guess I messed with something and that whats caused it to not work.