Player not taking damage with hit collidor

I’m very new to unity, and currently i’m trying to get my player to take damage from shots fired (Raycasts) from an enemy NPC. What currently works is that the player can damage the enemy NPC’s when fired, but it doesn’t work the opposite way, and i can’t seem to figure out why.

Gun Class:

using UnityEngine;
using System.Collections;

[RequireComponent (typeof (AudioSource))]
public class Gun : MonoBehaviour {

    public enum GunType {Semi,Burst,Auto};
    public GunType gunType;
    public float rpm;
    public LayerMask collisionMask;
    public float damage = 1;

    // Components
    public Transform spawn;
    //public Transform shellEjectionPoint;
    //public Rigidbody shell;
    private LineRenderer tracer;

    // System:
    private float secondsBetweenShots;
    private float nextPossibleShootTime;

    void Start() {
        secondsBetweenShots = 60/rpm;
        if (GetComponent<LineRenderer>()) {
            tracer = GetComponent<LineRenderer>();
        }
    }

    public void Shoot() {

        if (CanShoot()) {
            Ray ray = new Ray(spawn.position,spawn.forward);
            RaycastHit hit;

            float shotDistance = 20;

            if (Physics.Raycast(ray,out hit, shotDistance)) {
                shotDistance = hit.distance;

                // just testing here, dont mind this!
                if(hit.transform.tag == "Player") {
                    Debug.Log ("Player Hit");
                }

                if(hit.collider.GetComponent<Entity>()) {
                    Debug.Log("Taking Damage");
                    hit.collider.GetComponent<Entity>().takeDamage(damage);
                }


            }

            nextPossibleShootTime = Time.time + secondsBetweenShots;

            audio.Play();

            if (tracer) {
                StartCoroutine("RenderTracer", ray.direction * shotDistance);
            }

            //Rigidbody newShell = Instantiate(shell,shellEjectionPoint.position,Quaternion.identity) as Rigidbody;
            //newShell.AddForce(shellEjectionPoint.forward * Random.Range(150f,200f) + spawn.forward * Random.Range(-10f,10f));
        }

    }

    public void ShootContinuous() {
        if (gunType == GunType.Auto) {
            Shoot ();
        }
    }

    private bool CanShoot() {
        bool canShoot = true;

        if (Time.time < nextPossibleShootTime) {
            canShoot = false;
        }

        return canShoot;
    }

    IEnumerator RenderTracer(Vector3 hitPoint) {
        tracer.enabled = true;
        tracer.SetPosition(0,spawn.position);
        tracer.SetPosition(1,spawn.position + hitPoint);

        yield return null;
        tracer.enabled = false;
    }
}

Entity class, which Player.cs and Enemy.cs extend:

using UnityEngine;
using System.Collections;

public class Entity : MonoBehaviour {
    // this class will model our enemies
    // enemy health
    public float health;

    public virtual void takeDamage(float dmg) {
        // subtract dmg points from health
        health -= dmg;
        // log it
        Debug.Log (health);

        if(health <= 0) {
            // kill enemy
            die();
        }
    }

    public virtual void die() {
        // log that enenmy is dead
        //Debug.Log ("Dead");
        // destry the game object
        Destroy (gameObject);
    }
}

And the Enemy.cs class;

using UnityEngine;
using System.Collections;

public class Enemy : Entity {
    // add player expereicne points
    public float expOnDeath;
    // get reference to player
    private Player player;

    void Start() {
        // find the game object with player tag
        player = GameObject.FindGameObjectWithTag ("Player").GetComponent<Player>();
    }

    // override base die method, but with added functionality
    public override void die() {
        // add exp points
        player.AddExpereince (expOnDeath);
        base.die ();
    }
}

And the player.cs class

using UnityEngine;
using System.Collections;

public class Player : Entity {

    private int level;
    // current exp level
    private float currentExpLevel;
    // exp required to level up next
    private float expToLevel;
    public GameGUI gui;

    void Start() {
        gui = GameObject.FindGameObjectWithTag ("GUI").GetComponent<GameGUI> ();
        // by default the players level will be set to 1
        LevelUp ();
    }

    public override void die() {
        base.die ();
    }

    public void AddExpereince(float exp) {
        currentExpLevel += exp;
        if(currentExpLevel >= expToLevel) {
            currentExpLevel -= expToLevel;
            LevelUp();
        }
        gui.setPlayerExp (level);
        //Debug.Log ("EXP: "+currentExpLevel+" Level: "+level);
    }


    private void LevelUp() {
        // increase exp level
        level++;
        expToLevel = level * 50 + Mathf.Pow (level * 2,2);

        AddExpereince (0);
    }
}

This may not your issue, but it is probably worth checking.

You are raycasting and retrieving a single collision. Then, checking whether that one collision was against an Entity and applying damage in that case.

If you happen to be raycasting from within a gun, or from within the NPC, it is likely that the one collision being reported (which is the first one) is not the Entity (but the Gun, for instance), and thus it is essentially being ignored.

You might want to verify whether that is the case, and if it is, some possible solutions would be:

  • To filter some layers so that you don’t get other collisions.
  • To start the raycast from further away.
  • To raycast for multiple collisions and iterate over all of them.

For the last approach, which is probably the easiest and safest, you can use Unity - Scripting API: Physics.RaycastAll