繁体   English   中英

Unity 中的 Json 序列化 - NullReferenceException:未将对象引用设置为对象的实例

[英]Json Serialization in Unity - NullReferenceException : Object reference not set to an instance of an object

我创建了几个自定义类来读取 Unity 中的 json 文件。

水果.cs

[System.Serializable]
public class Fruits 
{
    public Apple[] apples;
}

苹果.cs

[System.Serializable]
public class Apple 
{
    public string appleName;
}

MyClass.cs

public class MyClass : MonoBehaviour{

private Fruits fruits;

public void classSetup(){
    StartCoroutine(JsonReader());     
    String appleName = fruits.apples[0].appleName;   -------> this is the line trigger the exception. 
    Debug.Log(appleName); 
}

Ienumerator JsonReader(){
   .........unrelated codes hidden...............
   if (Url.Contains(":/") || Url.Contains("://") || Url.Contains(":///"))
        {
            UnityWebRequest www = UnityWebRequest.Get(Url);
            yield return www.SendWebRequest();
            JsonText = www.downloadHandler.text;
        }

        fruits = JsonUtility.FromJson<Fruits>(JsonText);

}
}

JsonReader(我创建的 IEnumerator)工作正常,因为 Debug.Log 打印出我期望的 appleName 但“String appleName .....”行触发异常(NullReferenceException : Object reference not set to an instance of an object。)

我阅读了有关如何修复空异常的帖子,但无法找到有关如何为自定义序列化类执行此操作的帮助。 简单地做fruits = new Fruits() 是行不通的。 我怀疑那是因为我没有实例化这些字段。 但是如果我在 Fruits 类中有很多字段怎么办? 如果我不能只做“fruits.apples = new Apple[5]”,因为长度取决于 json 输入并且可能不是 5,该怎么办?

任何帮助将不胜感激。

我不完全确定那个。 但我认为问题是,Unity 过早地到达字符串 apple ,因为您启动了一个协程,并且当您创建 json 对象时,Unity 正在继续并尝试获取一个值,但该值尚不存在。 所以你可以尝试的是自定义事件。

//Create a delegate and and event to fire at a certain point of time
public delegate void FruitsLoadedEvent FruitsLoadedEvent();
public static event FruitsLoadedEvent OnFruitsLoaded;

public void classSetup(){
    //Subscribe to the event
    OnFruitsLoaded += CreateApple;
    StartCoroutine(JsonReader());     
}

Ienumerator JsonReader(){
    .........unrelated codes hidden...............
    if (Url.Contains(":/") || Url.Contains("://") || Url.Contains(":///"))
    {
        UnityWebRequest www = UnityWebRequest.Get(Url);
        yield return www.SendWebRequest();
        JsonText = www.downloadHandler.text;
    }

    fruits = JsonUtility.FromJson<Fruits>(JsonText);
    //Invoke the event after checking, if anyone is subscribed
    OnFruitsLoaded?.Invoke();
}

private void CreateApple() {
    String appleName = fruits.apples[0].appleName;
}

我真的希望能帮到你!

启动协程不会延迟启动它本身的方法。 如果这样做就没有意义,因为您将失去将其设为协程的全部原因。

您想要做的是将您的代码移动到在接收到结果应执行的例程中,例如

public class MyClass : MonoBehaviour
{  
    public void classSetup()
    {
        StartCoroutine(JsonReader());     
    }

    IEnumerator JsonReader()
    {
       // .........unrelated codes hidden...............
       if (Url.Contains(":/") || Url.Contains("://") || Url.Contains(":///"))
       {
            UnityWebRequest www = UnityWebRequest.Get(Url);
            yield return www.SendWebRequest();
            JsonText = www.downloadHandler.text;
        }

        var fruits = JsonUtility.FromJson<Fruits>(JsonText);

        String appleName = fruits.apples[0].appleName;   -------> this is the line trigger the exception. 
        Debug.Log(appleName); 
   }
}

或者使用回调

public class MyClass : MonoBehaviour
{
    public void classSetup()
    {
        StartCoroutine(JsonReader(HandleResult));     

        // or the same as lambda expression
        //StartCoroutine(JsonReader(fruits => 
        //{
        //    String appleName = fruits.apples[0].appleName;   -------> this is the line trigger the exception. 
        //    Debug.Log(appleName); 
        //}));
    }

    IEnumerator JsonReader(Action<Fruits> onResult)
    {
       // .........unrelated codes hidden...............
       if (Url.Contains(":/") || Url.Contains("://") || Url.Contains(":///"))
       {
            UnityWebRequest www = UnityWebRequest.Get(Url);
            yield return www.SendWebRequest();
            JsonText = www.downloadHandler.text;
        }

        var fruits = JsonUtility.FromJson<Fruits>(JsonText);

        onResult?.Invoke(fruits);
   }

   private void HandleResult(Fruits fruits)
   {
       String appleName = fruits.apples[0].appleName;   -------> this is the line trigger the exception. 
       Debug.Log(appleName); 
   }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM