Unity编辑器模式下List元素构造函数未正确初始化字符串问题
解决Unity Inspector中List元素字符串无法从构造函数初始化的问题
我来帮你搞定这个问题——你遇到的情况其实是Unity序列化机制和常规C#构造函数执行时机不匹配导致的。虽然你的构造函数确实执行了(所以能看到"Call test"的日志),但Unity在序列化List元素的过程中,会在构造函数调用后重置那些没有序列化数据的字段,把字符串清空成默认的空值。
下面给你两种靠谱的解决方案,你可以根据需求选:
方案1:利用序列化回调接口(推荐)
通过实现ISerializationCallbackReceiver接口,在Unity完成序列化操作后再初始化字段,这样就不会被序列化系统覆盖了。
代码示例:
using UnityEngine; [System.Serializable] public class YourDataClass : ISerializationCallbackReceiver { public string name; public string description; public YourDataClass() { Debug.Log("Call test"); // 这里的初始化会被序列化覆盖,所以移到回调里执行 } public void OnBeforeSerialize() { // 序列化前的操作,这里暂时不需要 } public void OnAfterDeserialize() { // 检查字段是否为空,为空则设置占位文本 if (string.IsNullOrEmpty(name)) { name = "默认名称"; } if (string.IsNullOrEmpty(description)) { description = "默认描述文本"; } } } // 挂载在GameObject上的脚本示例 public class YourBehaviour : MonoBehaviour { public List<YourDataClass> dataList; }
这样修改后,当你在Inspector里点击List的加号添加新元素时,OnAfterDeserialize会在序列化完成后触发,自动给空的name和description设置占位文本,而且构造函数的日志也会正常输出。
方案2:自定义Editor按钮添加元素
如果你更倾向于手动控制元素的创建,可以写一个自定义Editor类,添加一个按钮来创建带默认值的List元素:
代码示例:
using UnityEditor; using UnityEngine; using System.Collections.Generic; [CustomEditor(typeof(YourBehaviour))] public class YourBehaviourEditor : Editor { public override void OnInspectorGUI() { // 先绘制默认的Inspector界面 DrawDefaultInspector(); YourBehaviour targetScript = (YourBehaviour)target; // 添加自定义按钮 if (GUILayout.Button("添加带默认值的元素")) { YourDataClass newData = new YourDataClass(); newData.name = "默认名称"; newData.description = "默认描述文本"; // 如果List还没初始化,先实例化 if (targetScript.dataList == null) { targetScript.dataList = new List<YourDataClass>(); } targetScript.dataList.Add(newData); EditorUtility.SetDirty(targetScript); } } }
这种方法需要用户点击自定义按钮来添加元素,不过能完全控制初始化的过程,避免序列化机制的干扰。
为什么原来的构造函数不行?
简单来说,Unity在处理序列化的List元素时,流程是这样的:
- 调用构造函数创建实例
- 尝试从序列化数据(新元素没有历史数据)填充字段
- 没有序列化数据的字段会被重置为类型默认值(字符串就是空)
所以你在构造函数里设置的字符串会被这一步覆盖,而序列化回调接口是在这之后执行的,所以能保留住初始化的值。
内容的提问来源于stack exchange,提问作者Mc Midas
相关产品推荐
相关产品推荐

