Unity c# cписок не успевает инициализироваться в конструкторе

217
10 января 2018, 15:39

Делаю 2d тавер-дефенс, решил сделать конструктор для удобного создания башен, но столкнулся с ошибкой NullReferenceException: Object reference not set to an instance of an object при назначении башне спрайта и характеристик(во втором классе, строчке selftower = gl.AllTowers [(int)selftype]; чуть ниже.

Проблема заключается в glили FindObjectOfType<GameLogic>(); поскольку именно они возвращают null, но вот почему они не работают, для меня не очевидно. Я так же пробовал GetComponent<GameLogic>().AllTowers [(int)selftype] но и это не помогло. Практически на 100% уверен, что моя проблема в какой-то мелкой ошибке, которой я не замечаю, посмотрите пожалуйста свежим взглядом...

Есть два класса:

Конструктор:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tower{
    public float range,Cooldown;
    public Sprite Spr;
    public Tower(float range, float cd,string path){
        this.range = range;
        Cooldown = cd;
        Spr = Resources.Load<Sprite> (path);
    }
}
public class Towerprojectile{
}
public enum TypeTower{
    First_tower,Second_tower
}
public class GameLogic : MonoBehaviour {
    public List<Tower> AllTowers =  new List<Tower>();
    public void Awake(){
        AllTowers.Add (new Tower (40, 0.3f,"TowerSpr/First"));
        AllTowers.Add (new Tower (70, 0.9f,"TowerSpr/Second"));
    }
}

Класс логики башен:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Towersrc : MonoBehaviour {
    public GameObject Projectile;
    GameLogic gl;
    Tower selftower;
    public TypeTower selftype;
    private void Start(){
        gl = FindObjectOfType<GameLogic>();
        selftower = gl.AllTowers [(int)selftype];
        GetComponent<SpriteRenderer> ().sprite = selftower.Spr;
    }

Как реализовывал Initialize(2-й способ, который я пробовал):

public void Initialize(){
        AllTowers.Add (new Tower (40, 0.3f, "TowerSpr/First"));
        AllTowers.Add (new Tower (70, 0.9f, "TowerSpr/Second"));
    }

В Tower:

gl = FindObjectOfType<GameLogic>();
//      GetComponent<GameLogic> ().Initialiaze ();
        gl.Initialize();
//      selftower = GetComponent<GameLogic>().AllTowers [(int)selftype];
        selftower = gl.AllTowers[(int)selftype];

Спасибо за внимание, при необходимости, могу дать ссылку на гитхаб проекта.

Answer 1

Ваш компонент GameLogic должен быть добавлен в сцену и присутствовать в ней перед созданием башен. Он у вас инициируется на Awake и по идее должен срабатывать раньше чем будет вызван в Start у башни. Ваш конструктор на сколько я понимаю должен быть единственным в сцене, можно посмотреть в сторону синглтона и создать в классе статик ссылку на конструктор(то бишь на самого себя), чтобы получать доступ к конструктору в любом классе без использования Find.

public class GameLogic : MonoBehaviour {
public List<Tower> AllTowers =  new List<Tower>();
public static GameLogic instance = null;
public void Awake(){
    if (instance) 
    {
        Destroy(this);
        return;
    }
    instance = this;
    AllTowers.Add (new Tower (40, 0.3f,"TowerSpr/First"));
    AllTowers.Add (new Tower (70, 0.9f,"TowerSpr/Second"));
}
}

Это и быстрее и можно в момент инициализации проверять что второй объект с конструтором в сцене случайно создан не был. А в башнях обращаемся к нему вот так GameLogic.instance.AllTowers [(int)selftype]

READ ALSO
Классы. C#. Вывод результатов

Классы. C#. Вывод результатов

Доброго вечера всем обитателем портала (форума)К экзамену были даны практические задания (краткие) по классам

340
Сервис по реверсу MD5

Сервис по реверсу MD5

Передо мной встала задача - реверс md5 хеша 4 произвольных байтТо есть, другими словами, мне надо написать сервис из 1 метода - метод получает...

256
Вернуть исходную позицию анимации

Вернуть исходную позицию анимации

Есть объект, который меняет свой scale в анимации, после animationStop(); анимация останавливается с тем размером, с которым в этот момент проигрывалась,...

238
Домены приложений, время жизни

Домены приложений, время жизни

Рихтер пишет, что так как у типов в другом домене нету корней, то в CLR пошли на хитрость: прокси объекты живут ~5 минут с момента последнего обращения,...

229