简体   繁体   中英

C# OnTriggerEnter NullReferenceException

I'm using the ZDK from Zigfu for Game Project on my study. I took the standard avatar and attached two colliders (sphere colliders with rigid body) to the hands. One for the left hand, and one for the right hand. I build some (24) box colliders around the avatar, to track if the hands are entering a new area. Every box has an "id" from 0 to 23 an the following script:

using UnityEngine;
using System.Collections;

public class handsTracking : MonoBehaviour 
{
    public int id;

    void OnTriggerEnter (Collider other) {
        if(other.tag == "handsLeftTracking"){
            print("leftHand entered: " + id);
            playerCommunication.activity += 0.1f;
            playerCommunication.handsLeft[id] = true; //here ist the exception
        }
        else if (other.tag == "handsRightTracking"){
            print("rightHand entered: " + id);
            playerCommunication.activity += 0.1f;
            playerCommunication.handsRight[id] = true; //here ist the exception
        }
    }
    void OnTriggerExit (Collider other) {
        if(other.tag == "handsLeftTracking"){
            print("leftHand exited: " + id);
            playerCommunication.activity += 0.01f;
            playerCommunication.handsLeft[id] = false; //here ist the exception
        }
        else if (other.tag == "handsRightTracking"){
            print("rightHand exited: " + id);
            playerCommunication.activity += 0.01f;
            playerCommunication.handsRight[id] = false; //here ist the exception
        }
    }
}

In another script on the player I want to use these collisions. The handsTracking.cs should only edit the values in the playerCommunication.cs script:

using UnityEngine;
using System.Collections;

public class playerCommunication : MonoBehaviour {

    public static bool[] handsRight;
    public static bool[] handsLeft;
    public static float activity;
    public float fallback;

    // Use this for initialization
    void Awake () {
        activity = 0.0f;
    }

    // Update is called once per frame
    void Update () {
        if((activity - fallback * Time.deltaTime) >= 0.0f){
            activity -= fallback * Time.deltaTime;
        }
    }

    void OnGUI () {
        GUI.Box (new Rect (10,200,150,20), "Activity: " + activity);    
    }
}

This works fine, so far. But I'm getting the following exceptions:

NullReferenceException: Object reference not set to an instance of an object
handsTracking.OnTriggerEnter (UnityEngine.Collider other) (at Assets/SeriousGame/Scripts/handsTracking.cs:19)

If I commend out lines where I tried to edit the array, the errors are gone. I tried to call a function in the playerCommunication script, or to handle the arrays in the handsTracking.cs , but nothing works. I don't understand the link between the collision and the array?!

Your array haven't been never initialized. You got a NullReferenceException because your array is a reference to null since it hasn't be allocated nowhere.

For example you can init them inside Awake :

int[] array1 = new int[5];

public static bool[] handsLeft;

// Use this for initialization
void Awake () {
    activity = 0.0f;
    handsLeft = new bool[ARRAY_SIZE];
}

Maybe you have tried to initialized those array fields from inspector, but they are declared as static so Unity3D won't serialize them when you switch from editor to play mode.

Pay attention that a static field would be shared by all instances of playerCommunication class. So, if you want to have several GameObject to use this script, with different values inside your arrays, you shouldn't declare them as static.

If you want effectively declare them as static, since you can't know the order of creation of your classes, it would be better initialize them in a class static construcor:

static playerCommunication ()
{
     handsLeft = new bool[ARRAY_SIZE];
     handsRight = new bool[ARRAY_SIZE];
}

The reason you get a nullpointerexception, is because you try to add an object in the array which isn't initialised yet.

You have the following declaration:

public int id;

After that, you have the following line of code:

print("leftHand entered: " + id);

Change that to, for example:

Debug.Log("ID value is now: " + id);

You will probably see the following:

ID value is now: null

You haven't given id a value yet. When you call playerCommunication.handsLeft[id] = true; , you are actually trying to set the null'est value of the array to true . Make sure you set the id -value to something. You say every box has a id value from 0 to 23. Did you set that correctly in the Unity properties view?

My guess as to the reason you're getting the exception is because you're not accessing the playerCommunication script that's on the player, instead it's trying to use the one in the script folder, which (I imagine) doesn't have anything set on the public handsRight etc.

What you need to do is replace lines like this:

playerCommunication.handsLeft[id] = true;

with this:

GameObject.Find("Avatar").GetComponent<playerCommunication>().handsLeft[id] = true;

where "Avatar" will be the name of the avatar/player game object, and playerCommunication is the script within that object which has the handsLeft public bool.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM