我想制作一个程序,如果从检查器获取TextAsset(它放在'ExampleEditor'中),它会创建一个自定义数据实例以使用混合形状动画。
首先,我使用[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有关吗?
答案 0 :(得分:8)
你的问题不是很清楚,但我想知道你不理解的是什么。
我的策略是使用TextAsset,从TextAsset解析字符串 最后将Matrix实例创建为'Example.cs'中的字段变量。
您没有解释您是如何做到的(也许从自定义检查器调用解析函数?)。 但是,尽管如何设置从编辑器初始化字段,如果字段不可序列化,则从编辑器切换到播放模式时它将为null 。
这是因为当进入播放模式时,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
将重新初始化,您最终将会对空列表的引用。
这是一个很好的blog post,解释了Unity3D
如何处理对象序列化的详细信息。读吧!