对C#和Unity来说是新手,大约2天不能解决此问题。
我不知道为什么,但是在ItemOnGround
行的Debug.Log
类中总是出现此错误:
NullReferenceException: Object reference not set to an instance of an object
我尝试使用FetchItemById
方法,但仍然无法正常工作。即使我只是复制并粘贴Slot
类中的所有内容,它仍然无法正常工作。我尝试将其附加到其他GameObject,但仍然无法正常工作。是线程问题还是我做错了?
谢谢您的帮助
这里是如何在Unity中附加脚本:Screenshot
所以我有3 .cs
ItemDatabase
using System.Collections;
using System.Collections.Generic;
using System.IO;
using LitJson;
using UnityEngine;
public class ItemDatabase : MonoBehaviour
{
private List<Item> database = new List<Item>();
private JsonData itemData;
void Start()
{
SetLanguagePath();
ConstructItemDatabase();
}
public void SetLanguagePath()
{
itemData = JsonMapper.ToObject(File.ReadAllText(Application.streamingAssetsPath + "/en_Items.json"));
}
public Item FetchItemById(int id)
{
for (int i = 0; i < database.Count; i++)
{
if (database[i].Id == id)
{
return database[i];
}
}
return null;
}
public Item FetchItemBySlug(string slug)
{
for (int i = 0; i < database.Count; i++)
{
if(database[i].Slug == slug)
{
return database[i];
}
}
return null;
}
void ConstructItemDatabase()
{
for (int i = 0; i < itemData.Count; i++)
{
Item newItem = new Item();
newItem.Id = (int)itemData[i]["id"];
newItem.Title = itemData[i]["title"].ToString();
newItem.Value = (int)itemData[i]["value"];
newItem.Power = (int)itemData[i]["stats"]["power"];
newItem.Defense = (int)itemData[i]["stats"]["defense"];
newItem.Vitality = (int)itemData[i]["stats"]["vitality"];
newItem.Description = itemData[i]["description"].ToString();
newItem.Stackable = (bool)itemData[i]["stackable"];
newItem.Type = itemData[i]["type"].ToString();
newItem.Slug = itemData[i]["slug"].ToString();
newItem.Sprite = Resources.Load<Sprite>("Sprites/Items/" + newItem.Slug);
database.Add(newItem);
}
}
}
public class Item
{
public int Id { get; set; }
public string Title { get; set; }
public int Value { get; set; }
public int Power { get; set; }
public int Defense { get; set; }
public int Vitality { get; set; }
public string Description { get; set; }
public bool Stackable { get; set; }
public string Type { get; set; }
public string Slug { get; set; }
public Sprite Sprite { get; set; }
}
Slot
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Slot : MonoBehaviour
{
bool hasItem = true;
private void Start()
{
InitializeSlot();
}
void InitializeSlot()
{
if (hasItem)
{
ItemDatabase database = GameObject.Find("Inventory").GetComponent<ItemDatabase>();
Item item = database.FetchItemById(0);
Debug.Log(item.Slug);
}
}
}
ItemOnGround
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemOnGround : MonoBehaviour
{
void Start()
{
InitializeItem();
}
void InitializeItem()
{
ItemDatabase database = GameObject.Find("Inventory").GetComponent<ItemDatabase>();
Item item = database.FetchItemBySlug("apple");
Debug.Log(item.Slug);
}
}
和en_Items.json
[
{
"id": 0,
"title": "Apple",
"value": 1,
"stats": {
"power": 1,
"defense": 1,
"vitality": 10
},
"description": "Tasty apple",
"stackable": true,
"type": "food",
"slug": "apple"
},
{
"id": 1,
"title": "Plum",
"value": 1,
"stats": {
"power": 1,
"defense": 1,
"vitality": 10
},
"description": "Juicy plum",
"stackable": true,
"type": "food",
"slug": "plum"
}
]
Unity Engine具有特定的Order of Execution。
这定义在每个脚本中执行Unity回调的顺序。
例如,您的MonoBehaviours中的所有Awake()
回调将在任何Start()
回调之前执行。
就是说,这并不意味着它控制着来自不同行为的各个Start()
回调的执行顺序。
在您的示例中。 Start()
行为的ItemOnGround
回调可能在ItemDatabase
之前被调用。在这种情况下,您要调用尚未初始化的ItemDatabase
。所以这是我的建议:
方法1:
[知道在Awake()
之前调用了Start()
,您可以通过将ItemDatabase
更改为:来初始化Start()
:
void Awake()
{
SetLanguagePath();
ConstructItemDatabase();
}
方法2:
您可以调整Script Execution Order settings。在“编辑”>“项目设置”中。
这使您可以为每个MonoBehaviours赋予优先顺序。
通过给脚本ItemDatabase
一个比ItemOnGround
更低的数字(更高的优先级,您是在告诉引擎在ItemDatabase.Start()
之前调用ItemOnGround.Start()
。