1

我想制作一个程序,如果它从检查器中获取 TextAsset(它放置在“ExampleEditor”中),它会制作一个自定义数据实例以使用 blendshape 动画。

起初,我制作了不使用 [System.Serializable] 的自定义数据类。

public class Matrix {
    public int row;
    public int col;
    public double[,] mat;
}

我的策略是采用 TextAsset,从 TextAsset 解析字符串,最后将 Matrix 实例制作为“Example.cs”中的字段变量。我认为当它首先被初始化和分配时,我能够在 Example 实例中使用该变量。但是,它没有用,它抛出了“NullReferenceException”。

所以我找到了使用“[System.Serializable]”的解决方案。它确实奏效了。(而且我知道 Unity3D 没有为其序列化方法提供多维数组。)

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

[System.Serializable]
public class Matrix {
    [System.Serializable]
    public class mRow {
        public List<float> aRow = new List<float>();
    }

    [HideInInspector]
    [SerializeField]
    public int row;

    [HideInInspector]
    [SerializeField]
    public int col;

    //[HideInInspector]
    [SerializeField]
    public List<mRow> mat = new List<mRow>();
}

最后,我知道了解决方案,但我不知道为什么会出现这个问题。它与GC有关吗?

4

1 回答 1

9

你的问题不是很清楚,但我想知道你不明白什么。

我的策略是采用 TextAsset,从 TextAsset 解析字符串,最后将 Matrix 实例制作为“Example.cs”中的字段变量。

你没有解释你是怎么做到的(也许从自定义检查器调用解析函数?)。但是,尽管您如何设法从编辑器初始化字段,但如果该字段不可序列化,则在从编辑器切换到播放模式时它将为空

发生这种情况是因为进入播放模式时,会Unity3D序列化C#填充C++引擎相关类的所有类。如果一个字段不是 Unity 可以序列化的类型的公共字段(甚至是标有 的私有字段SerializeFieldAttribute,总是Unity可以序列化的类型),Unity3D则不会对其进行序列化。

因此,当您切换到播放模式时,引用将为空。

换句话说,您想从编辑器初始化的所有字段都必须是可序列化的,以便在播放模式下使用。

[SerializeField]
public List<mRow> mat = new List<mRow>();

上面的代码没有多大意义。如果您打算从检查器初始化一个可序列化字段,请不要通过代码初始化它,否则您最终可能会丢失引用。此类错误的示例:

[SerializeField]
private List<int> aList;

public void Start()
{
  aList = new List<int>();
} 

上面的代码会引起麻烦。如果您已经aList从检查器初始化,它将被正确序列化,但是当您切换到播放模式时,Start回调被调用,aList将被重新初始化,并且您最终会引用一个空列表。

这是一篇很好的博客文章,详细解释了如何Unity3D处理对象的序列化。阅读!

于 2013-07-27T16:07:07.567 回答