UNITY |方法返回null

问题描述 投票:0回答:1

对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"
    }
]
c# unity3d
1个回答
0
投票

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()

© www.soinside.com 2019 - 2024. All rights reserved.