Raycast to get gameobject being hit to run script and function on gameobject

大憨熊 提交于 2020-01-07 01:22:34

问题


I'm in the process of getting multiple enemies to work in my game for my college project. I have a player with a ShootGun script which raycasts the gun and detects whether or not the object hit is one of the enemy colliders (tagged with Enemy_Head, _Torso and _Limb). If it is, it will get the gameobject of the enemy hit and the enemyHealth script component on that gameobject and will then call public functions on that script. Currently, when the ShootGun script tries to get the component / script it says the following error:

NullReferenceException: Object reference not set to an instance of an object ShootGun.gunFire () (at Assets/Scripts/Gun/ShootGun.cs:107)

UPDATED ERROR CODE:

NullReferenceException: Object reference not set to an instance of an object ShootGun.gunFire () (at Assets/Scripts/Gun/ShootGun.cs:113)

Line 113 = enHit.enemyShotTorso();

The error appears for each line where enHit tries to call a function from the enemyHealth script.

The following is the raycast within my ShootGun script:

// Raycasting for bullet projection against obstacles within the world (WIP)
            float gunRayDistance = 50f;

            Ray ray = GetComponent<Camera>().ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));

            // Name what for the raycast collides with (used to reference the target point)
            RaycastHit hit;

            // The actual raycast
            if(Physics.Raycast(ray, out hit, gunRayDistance, 1 << 9) || Physics.Raycast(ray, out hit, gunRayDistance, 1 << 8)) {
                Debug.Log("Bullet Hit");

                EnemyHealth enHit = hit.collider.gameObject.GetComponent<EnemyHealth>();

                // Checking if the raycast (bullet) collided with objects tagged with "Enemy_Head".
                if (hit.collider.gameObject.CompareTag("Enemy_Head")) {
                    Debug.Log ("Headshot!");
                    //hitPoint = hit.collider.gameObject;
                    enHit = hit.collider.gameObject.GetComponent<EnemyHealth>();
                    enHit.enemyShotHead();
                }
                // Checking if the raycast (bullet) collided with objects tagged with "Enemy_Torso".
                if (hit.collider.gameObject.CompareTag("Enemy_Torso")) {
                    Debug.Log ("Body-shot!");
                    //hitPoint = hit.collider.gameObject;
                    enHit = hit.collider.gameObject.GetComponent<EnemyHealth>();
                    enHit.enemyShotTorso();
                }
                // Checking if the raycast (bullet) collided with objects tagged with "Enemy_Limb".
                if (hit.collider.gameObject.CompareTag("Enemy_Limb")) {
                    Debug.Log ("Limb-shot!");
                    enHit = hit.collider.gameObject.GetComponent<EnemyHealth>();
                    enHit.enemyShotLimb();
                }
                // The point of contact with the model is given by the hit.point (to not cause z-fighting issues with layering)
                Vector3 bulletHolePosition = hit.point + hit.normal * 0.01f;
                // Rotation to match where it hits (between the quad vector forward axis and the hit normal)
                Quaternion bulletHoleRotation = Quaternion.FromToRotation(-Vector3.forward, hit.normal);
                GameObject hole = (GameObject)GameObject.Instantiate(bulletHolePrefab, bulletHolePosition, bulletHoleRotation);
                // Destroy the instantiated gameobject of the bulletHole after a delay of 5 seconds.
                Destroy (hole, 5.0f);
            }                                                                                                                    
        }

The following is my EnemyHealth script:

public class EnemyHealth : MonoBehaviour {

public float enemyHealth = 100.0f;

// Use this for initialization
void Start () {

}
// Update is called once per frame
void Update () {
    enemyDeath ();
}

public void enemyShotHead() {
    enemyHealth -= 60f;
    Debug.Log (enemyHealth);
}

public void enemyShotTorso() {
    enemyHealth -= 40f;
    Debug.Log (enemyHealth);
}

public void enemyShotLimb() {
    enemyHealth -= 20f;
    Debug.Log (enemyHealth);
}

void enemyDeath() {
    if (enemyHealth <= 0.0f) {
        Debug.Log ("Enemy Killed");
        gameObject.SetActive(false);
    }
}

}

Any help with trying to figure out why it's not getting the reference / setting them would be greatly appreciated, thanks.


回答1:


enHit is likely null. Repace all your

hit.transform.gameObject.GetComponent<EnemyHealth>();

with

hit.collider.gameObject.GetComponent<EnemyHealth>();

You have about 4 of them in your script. You want to get the EnemyHealth Script attached to the object the Ray hit through the collider.

EDIT:

You also need to change

hit.transform.CompareTag("Enemy_Head")
hit.transform.CompareTag("Enemy_Torso")
hit.transform.CompareTag("Enemy_Limb")

to

hit.collider.gameObject.CompareTag("Enemy_Head")
hit.collider.gameObject.CompareTag("Enemy_Torso")
hit.collider.gameObject.CompareTag("Enemy_Limb")

This may NOT solve the current error you are getting but it is one of the problems that is causing that error.



来源:https://stackoverflow.com/questions/30020429/raycast-to-get-gameobject-being-hit-to-run-script-and-function-on-gameobject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!