2013-04-23 3 views
1

Я использую ZDK от Zigfu для Game Project в своем кабинете. Я взял стандартный аватар и привязал к себе два коллайдера (сферические коллайдеры с жестким телом). Один для левой руки, а другой для правой руки. Я строю несколько (24) полевых коллайдеров вокруг аватара, чтобы отслеживать, входят ли руки в новую область. Каждая коробка имеет «идентификатор» от 0 до 23 следующий сценарий:C# OnTriggerEnter NullReferenceException

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 
     } 
    } 
} 

В другом сценарии на плеере я хочу использовать эти столкновения. В handsTracking.cs следует изменять только значения в сценарии playerCommunication.cs:

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);  
    } 
} 

Это прекрасно работает, до сих пор. Но я получаю следующие исключения:

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

Если предаю из строк, в которых я пытался отредактировать массив, ошибки исчезли. Я попытался вызвать функцию в скрипте playerCommunication или обработать массивы в файле handsTracking.cs, но ничего не работает. Я не понимаю связь между столкновением и массивом ?!

+0

В строке 19, где произошла ваша ошибка, я вижу '}'. Я сбрасываю сверху, поэтому я не вижу простыни. На какой строке происходит ошибка? – Joetjah

+0

Ах, извините, я немного экспериментировал с кодом, поэтому ошибка здесь не соответствует коду. Я начал его снова, и это все еще строки с 'playerCommunication.handsLeft [id] = true ;, ... Здесь он выдает исключение ... – dome12b

ответ

3

Ваш массив никогда не инициализировался. У вас есть NullReferenceException, потому что ваш массив является ссылкой на null, так как он нигде не выделяется.

Например, вы можете инициализировать их внутри Awake:

int[] array1 = new int[5]; 

public static bool[] handsLeft; 

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

Может быть, вы пытались инициализировать эти поля массива от инспектора, но они объявлены как статические, так Unity3Dне будет сериализовать их при переключении от редактора до режима воспроизведения.

Обратите внимание, что статическое поле будет использоваться всеми экземплярами класса playerCommunication. Итак, если вы хотите, чтобы несколько GameObject использовали этот скрипт с разными значениями внутри ваших массивов, вы не должны объявлять их как статические.

Если вы хотите эффективно объявить их как статические, так как вы не можете знать порядок создания ваших классов, было бы лучше инициализировать их в классе статической construcor:

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

Инициализация массивов в функции awake() решена моя проблема, спасибо! – dome12b

0

Причина, по которой вы получаете исключение nullpointerexception, заключается в том, что вы пытаетесь добавить объект в массив, который еще не инициализирован.

Вы следующее заявление:

public int id; 

После этого, у вас есть следующие строки кода:

print("leftHand entered: " + id); 

Изменение, что, к примеру:

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

Вы вероятно, видят следующее:

ID value is now: null 

Вы еще не дали id значение. Когда вы вызываете playerCommunication.handsLeft[id] = true;, вы на самом деле пытаетесь установить нулевое значение массива на true. Убедитесь, что вы установили значение id. Вы говорите, что каждая ячейка имеет значение id от 0 до 23. Правильно ли вы установили это в представлении свойств Unity?

+0

Я установил идентификатор в инспекторе Unity. И, конечно, я проверил значение идентификаторов с помощью 'print (« id »):« Я попробовал Debug.Log до сих пор. Здесь переменные также верны: значение идентификатора теперь: 19 UnityEngine.Debug: Log (Object) handsTracking: OnTriggerEnter (Collider) (в Assets/SeriousGame/Scripts/handsTracking.cs: 11) ' – dome12b

0

Моя догадка, чтобы причина, по которой вы получаете исключение, заключается в том, что вы не получаете доступ к скрипту playerCommunication, который находится на проигрывателе, вместо этого он пытается использовать тот, который находится в папке сценария, который (я полагаю) не имеет ничего общего на публике handsRight и т. д.

Что вам нужно сделать, это заменить такие строки:

playerCommunication.handsLeft[id] = true; 

с этим:

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

, где «Аватар» будет именем аватара/игрок игрового объекта, и playerCommunication является сценарием внутри этого объекта, который имеет общественный BOOL handsLeft.

+0

handsRight объявлен статическим, поэтому он может получить доступ к прямому имени класса tough. – Heisenbug

+0

@Heisenbug это статично, но в Unity вы можете заполнить массив и установить его размер с помощью Inspector. Похоже, он установил размер и заполнил массив для объекта игрока, но сценарий в папке все еще не имеет. Отсюда исключение. –

+0

статическое поле не будет сериализовано при переключении между режимом редактора и воспроизведением. Поэтому, даже если он инициализировал его у инспектора, данные будут потеряны. – Heisenbug

Смежные вопросы