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

Unity中ScriptableObject传递对象引用后修改同步变更问题

问题根因说明
  • 当Terrain定义为class时,C#中class属于引用类型,你从SO中传递出去的是指向同一块内存的引用,修改引用指向的实例内容,自然会同步修改SO内的原始数据。
  • 就算你把Terrain改为struct(值类型)也会出问题,是因为你用Terrain[]数组存储数据:数组本身是引用类型,直接通过数组索引修改struct元素的属性/字段时,操作的是数组内的原始值,而非值副本,所以修改仍然会同步到SO数据中。
可行解决方案

方案1:传递实例前手动做深拷贝

无论Terrain是class还是struct,对外传递时都先复制一份独立副本,后续修改副本不会影响原始SO数据:

适用于class类型的Terrain

给Terrain新增Clone方法,示例代码如下:

public class Terrain
{
    public int terrainId;
    public float height;
    // 其余自定义属性

    public Terrain Clone()
    {
        return new Terrain
        {
            terrainId = this.terrainId,
            height = this.height,
            // 逐字段拷贝所有自定义属性
        };
    }
}

取实例时调用克隆方法即可:Terrain terrainCopy = mapSO.tiles[index].Clone();

适用于struct类型的Terrain

取元素时显式赋值给本地变量,不要直接操作数组内的元素:

// 错误写法:直接修改数组内的struct,会同步修改SO原始数据
mapSO.tiles[0].height = 3.5f;

// 正确写法:先拷贝到本地变量,修改的是独立副本
Terrain localTerrain = mapSO.tiles[0];
localTerrain.height = 3.5f;

如果后续需要把修改同步回SO,再手动赋值:mapSO.tiles[0] = localTerrain;即可。

方案2:初始化时全局拷贝SO数据,运行时只操作副本

可以在游戏启动时把SO的所有数据一次性深拷贝到运行时内存中,后续所有业务逻辑都只操作这份副本,完全不接触原始SO,从根源上避免误改原始配置:

public class MapRuntimeData : MonoBehaviour
{
    // 编辑器中赋值原始SO
    public Map originalMapSO;
    // 运行时使用的独立数据副本
    private Terrain[] _runtimeTiles;

    private void Awake()
    {
        // 初始化时全量拷贝
        _runtimeTiles = new Terrain[originalMapSO.tiles.Length];
        for (int i = 0; i < originalMapSO.tiles.Length; i++)
        {
            _runtimeTiles[i] = originalMapSO.tiles[i].Clone();
        }
    }

    // 对外只提供副本的访问接口
    public Terrain GetTerrain(int index)
    {
        return _runtimeTiles[index].Clone();
    }
}

该方案还可以避免编辑器模式下运行时修改SO,导致原始配置被永久改动的问题。

方案3:将Terrain改为只读结构

如果业务上没有修改Terrain属性的需求,可以直接把Terrain所有属性改为只读,从语法层面禁止意外修改:

public class Terrain
{
    // 仅开放get访问器,构造时赋值后不可修改
    public int TerrainId { get; }
    public float Height { get; }

    public Terrain(int terrainId, float height)
    {
        TerrainId = terrainId;
        Height = height;
    }
}

内容的提问来源于stack exchange,提问作者Yoaquin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:27:02