Массив пользовательских игровых объектов возвращает значение null в своих индексах после создания объектов?

Во время выполнения я сначала добавляю некоторые элементы в массив, затем записываю их значения в журнал (работает просто отлично), затем я создаю их экземпляры (все еще работает нормально), а затем я хочу изменить значения элементов массива, но для некоторых почему теперь индексы массива возвращают null? Кто-нибудь, кто знает, что происходит не так?

public class ListEquippedItems : MonoBehaviour
 {
 private static ListEquippedItems instance = null;
 public static ListEquippedItems Instance
 {
     get
     {
         if (instance == null) instance = new ListEquippedItems();

         return instance;
     }
 }

 [SerializeField]
 private GameObject[] currentlyEquippedItems = new GameObject[8];

 void Awake()
 {
     // Putting fake items into the currently equipped to test that items can actually be transfered to it
     for (int i = 0; i < currentlyEquippedItems.Length; i++)
     {
         //////////////////// In 3 below lines the array works just fine and returns proper values.
         currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().SetItemType((EffectTypes)i);
         currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().SetItemName("I am item: " + i);
         currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().SetItemIcon(RewardAssetContainer.Instance.commonExample);

         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemIcon().ToString());
         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemType().ToString());
         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemName());
     }
 }

 public void SetEquippedItem(EffectTypes _itemType, Sprite _itemIcon, string _itemName)
 {
     for (int i = 0; i < currentlyEquippedItems.Length; i++)
     {

         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemType().ToString());
         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemName());
         Debug.Log(currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemIcon().ToString());

     //////////////////// In 3 below lines the array returns null references, but why?
         if (currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().GetItemType() == _itemType)
         {
             currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().SetItemName(_itemName);
             currentlyEquippedItems[i].GetComponent<ListEquippedEntry>().SetItemIcon(_itemIcon);
             break;
         }
     }
 }  

person K_Nielsen...    schedule 03.10.2017    source источник
comment
Я не знаю тип вашего _itemType. Но можете ли вы попробовать также добавить toString() .Like .GetItemType().toString() == _itemType.toString())   -  person Thalthanas    schedule 03.10.2017
comment
Я пробовал это уже. Я почти уверен, что нет другого скрипта, который каким-либо образом обращается к этому массиву, и игровой объект не отключается или что-то в этом роде. Я понятия не имею, почему он возвращает нулевые значения для меня, но все же элементы и их спрайты видны в сцене -.-   -  person K_Nielsen...    schedule 03.10.2017
comment
Я не вижу никаких проблем с кодом, который вы представили, есть ли способ опубликовать код для SetItemName, SetItemType и SetItemIcon, поскольку они кажутся членами вашего класса ListEquippedEntry, и я считаю, что это может иметь некоторое влияние. На первый взгляд кажется, что ваш код должен работать нормально.   -  person    schedule 03.10.2017
comment
Каков результат операторов отладки, которые вы добавили перед разделом, вызывающим NPE?   -  person Draco18s no longer trusts SE    schedule 03.10.2017


Ответы (1)


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

У вас есть ListEquippedItems, закодированный аналогично синглтону, но технически это не синглтон. Я предполагаю, что объект, для которого вызывается SetEquippedItem(), не является тем же объектом, для которого вызывается Awake().

Способы, которыми это может произойти:

  1. Вы создаете игровой объект ListEquippedItems в иерархии. Это создает один экземпляр.
  2. Вы ссылаетесь на ListEquippedItems.Instance. Это создает еще один экземпляр.
  3. Вы создаете ListEquippedItems с помощью конструктора. Это создаст еще один экземпляр.
  4. У вас есть 2 (или более) потока, ссылающихся на ListEquippedItems.Instance одновременно. При правильном выборе времени оба потока могли видеть экземпляр как null и создавать новый экземпляр.

Как проверить, так ли это:

Добавьте следующий фрагмент кода в методы Awake() и SetEquippedItem():

if( this != instance )
{
    Debug.Log( "<methodName> invoked against non-singleton instance." );
}

Как решить проблему:

Создавайте ListEquippedItems только одним способом. Если вы хотите сохранить его в иерархии, сохраните экземпляр в методе Awake(), а не при ссылке на поле экземпляра.

Если вам нужен правильный синглтон, ознакомьтесь с этой статьей вики из вики Unity. Похоже, что в вики-записи здесь.

person Jaguar    schedule 03.10.2017
comment
Спасибо, вы были правы, я действительно создал сценарий, который вы объяснили! Вместо того, чтобы использовать ваше решение, которое вы предлагаете, я думаю, что лучше попытаюсь решить корень проблемы, два синглтона, или, вероятно, у меня возникнут другие проблемы где-то внизу по линии :) Большое спасибо за то, что указали мне правильное направление хотя, ты классный! Я хотел бы отметить urs как правильный ответ, но моя репутация слишком низкая, извините :/ - person K_Nielsen...; 04.10.2017
comment
Я обновил свой ответ парой ссылок, которые могут быть вам полезны. - person Jaguar; 04.10.2017
comment
Вы должны быть в состоянии принять ответ на свой вопрос независимо от того, сколько у вас повторений. Слева от ответа должна быть серая галочка, на которую можно нажать, под кнопками голосования вверх/вниз. - person Jaguar; 04.10.2017