You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重排List为何会更新无关的Dictionary?

问题原因:Unity序列化机制与自定义类构造函数的冲突

你遇到的现象本质是Unity序列化系统对无参构造函数的依赖,加上编辑模式与Play模式间的序列化交互导致的:

  1. 你的Person类标记了[System.Serializable],但没有提供无参的默认构造函数。Unity的序列化系统要求可序列化的自定义类必须有一个无参构造函数,否则在序列化/反序列化过程中会通过反射强制创建实例,这会引发不可预料的对象状态异常。

  2. 具体流程:

    • 第一次运行游戏: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被修改的现象。
  3. 解决方案:

    • 给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:15:19