重排List为何会更新无关的Dictionary?
问题原因:Unity序列化机制与自定义类构造函数的冲突
你遇到的现象本质是Unity序列化系统对无参构造函数的依赖,加上编辑模式与Play模式间的序列化交互导致的:
你的
Person类标记了[System.Serializable],但没有提供无参的默认构造函数。Unity的序列化系统要求可序列化的自定义类必须有一个无参构造函数,否则在序列化/反序列化过程中会通过反射强制创建实例,这会引发不可预料的对象状态异常。具体流程:
- 第一次运行游戏:
Start()方法创建两个Person实例(Dave和Jessica),添加到dict,同时将它们的引用加入lst。此时lst和dict指向同一个对象实例。 - 停止游戏后,Unity会将
lst中的Person对象序列化到场景/预制体文件中。由于Person没有无参构造函数,Unity无法正确保存对象引用,只能序列化字段值(name)。 - 当你在检视面板交换
lst的顺序后再次运行游戏:- Unity首先会反序列化
lst,尝试创建Person实例。因为没有无参构造函数,Unity会通过反射创建实例,此时可能出现对象实例混淆或字段赋值错误。 - 随后
Start()方法执行,再次创建新的Person实例添加到dict,但此时Unity的序列化异常已经导致dict中的实例与lst中的实例引用发生了错误关联,最终出现dict["daveID"].name被修改的现象。
- Unity首先会反序列化
- 第一次运行游戏:
解决方案:
- 给
Person类添加一个无参构造函数:[System.Serializable] public class Person { public string name; // 新增无参构造函数,供Unity序列化使用 public Person() { } public Person(string name) { this.name = name; } } - 如果你希望
lst只在运行时初始化,而不保存编辑模式下的修改,可以在Start()方法开头清空lst:private void Start() { lst.Clear(); // 清空序列化的列表数据 dict.Add("daveID", new Person("Dave")); dict.Add("jessID", new Person("Jessica")); foreach (var i in dict) { lst.Add(i.Value); } }
- 给
另外需要注意:Unity的序列化系统仅支持字段的序列化,不支持属性;同时,引用类型的序列化在编辑模式和Play模式间的交互需要严格遵循序列化规则,否则容易出现引用混乱的问题。
内容的提问来源于stack exchange,提问作者PinballJunior
相关产品推荐
相关产品推荐

