2016-05-23 4 views
5

Я застрял в довольно тупой ситуации: я создаю новый экземпляр родового класса, но он возвращает «странный» нуль.Единство: Нуль при создании нового экземпляра класса

Rule rule2 = new Rule(); // initiate the class 
    Debug.Log(rule2); //1st debug 
    rule2.RuleSetup(r: "CaughtEnough", li: 0); //setting up the parameters 
    Debug.Log(rule2.rule); //2nd debug 

первых отлаживать дает мне

null 
    UnityEngine.Debug:Log(Object) 

в то же время настройки параметров работы, а вторая отладка дает мне

CaughtEnough 
    UnityEngine.Debug:Log(Object) 

, который является тем, что должно быть в надлежащем классе пример.

Один (только до сих пор) вопрос, что это приносит мне, что если Whitin этого экземпляра класса Rule я называю

Invoke(rule, 0f); 

это дает мне ошибку NullReferenceException. Но в то же время фактическая функция

CaughtEnough(); 

работает просто отлично и, как ожидалось.

Любые идеи, что может быть источником проблемы и как ее преодолеть?

UPD также размещения установки часть класса Rule, как просили, хотя это просто

public class Rule : MonoBehaviour { 

public string rule; 

public int leftInt; 
public Dictionary<string, int> leftDict; 
public float countdown; 

public int outcome; 

public CatchManager catchMan; 
public Net net; 

// Use this for initialization 
void Start() { 
    RuleSetup(); 
} 

public void RuleSetup(string r = "NoRule", int li = 0, Dictionary<string, int> ld = null, float cd = float.PositiveInfinity) { 
    rule = r; 
    leftInt = li; 
    leftDict = ld; 
    countdown = cd; 
} 
..... 
+0

Просто проверьте, если rule2 равно нулю, делая если (Правила2 == NULL) {debug.log ("null")} else {Debug.Log ("Не null")}. Также опубликуйте свой класс Rule, чтобы мы могли видеть, что такое RuleSetup. – Programmer

+0

Спасибо, я проверил, как вы сказали, и rule2 действительно null. – Alex

ответ

14
public class Rule : MonoBehaviour{} 
Rule rule2 = new Rule(); 

Вы не можете использования new ключевых слов, чтобы создать новый экземпляр, если вы наследующий от MonoBehaviour.

Вы должны получить исключение, которое говорит:

Вы пытаетесь создать MonoBehaviour используя «новый» ключевое слово. Это запрещено. MonoBehaviours можно добавлять только с помощью AddComponent(). Кроме того, ваш сценарий может наследовать от ScriptableObject или нет базового класса на всех

Ваш код был бы работал, если у вас public class Rule {}, но у вас есть public class Rule : MonoBehaviour {}.

Создание нового экземпляра класса, производный от MonoBehaviour:

Пример Класс:

public class Rule : MonoBehaviour 
{ 
    public Rule(int i) 
    { 

    } 
} 

Если вы унаследовали от MonoBehaviour, вы должны либо использовать GameObject.AddComponent или Instantiate создать новый экземпляр Это.

Rule rule2 = null; 
void Start() 
{ 
    rule2 = gameObject.AddComponent<Rule>(); 
} 

ИЛИ

public Rule rulePrefab; 
Rule rule2; 
void Start() 
{ 
    rule2 = Instantiate(rulePrefab) as Rule; 
} 

Если Rule сценарий уже существует, и прикрепляют к GameObject, вам не нужно создавать/добавлять/экземпляр нового экземпляра этого сценария. Просто используйте функцию GetComponent, чтобы получить экземпляр скрипта из объекта GameObject, к которому он привязан.

Rule rule2; 
void Start() 
{ 
    rule2 = GameObject.Find("NameObjectScriptIsAttachedTo").GetComponent<Rule>(); 
} 

Вы заметите, что вы не можете использовать параметр в конструкторе, когда вы черпаете ваш скрипт из MonoBehaviour.



Создание нового экземпляра класса, который не вытекает из MonoBehaviour:

Пример класса: (Обратите внимание, что он не является производным от "MonoBehaviour"

public class Rule 
{ 
    public Rule(int i) 
    { 

    } 
} 

Если вы не inhe rit from MonoBehaviour, вы должны использовать ключевое слово new, чтобы создать новый экземпляр. Теперь вы можете использовать в конструкторе, если хотите.

Rule rule2 = null; 

void Start() 
{ 
    rule2 = new Rule(3); 
} 

EDIT:

В последней версии Unity, создавая новый экземпляр сценария, который наследует от MonoBehaviour с new ключевым словом не может дать вам ошибки и не может быть null слишком но все функции обратного вызова не будут выполняться. Они включают функции Awake, Start, Update и другие. Таким образом, вы все равно должны сделать это правильно, как указано в начале этого ответа.

+1

Не знал этого, спасибо. Это выглядит как действительно странная конвенция. – Alex

+1

@ Пользователи Alex New Unity испытывают то, что включает меня.О, и не забудьте сделать то же самое при создании экземпляра 'CatchManager' и' Net', которые находятся внутри скрипта 'Rule' – Programmer

+1

Еще раз спасибо, все остальное на самом деле является сплошными объектами с персоналом prefabs n '. Не знаю, почему я думал, что могу пойти только с классом в случае с Правилом :) – Alex

2

Просто аа следить, как я в конечном итоге делаю это, и почему:

  1. Я больше не наследую Rule класса от MonoBehaviour, чтобы избежать отслеживания секреции и удаления из геймобжекты, которые, казалось, были боль.

  2. Как Invoke метод не существует в общих классах, я заменил его с отражением, как описано here

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