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

Unity中C# 8反射设置结构体字段值失败的原因及解决方法

问题原因与修复方案

原因分析

PlayerData是值类型(struct),反射的FieldInfo.SetValue方法处理值类型时,会创建该实例的副本进行修改。你传入的playerData是值类型实例,SetValue实际修改的是这个副本的health字段,原变量完全没被改动,所以断言时health还是初始的100f。

修复方案

方案1:装箱+拆箱修改原实例

将值类型装箱为引用类型,修改装箱后的对象后再拆箱赋值回原变量,这样原实例就能被更新:

[Test]
public void SetValue_ChangesHealthUsingReflection()
{
    // Arrange
    var playerData = new PlayerData
    {
        name = "Test Player",
        level = 1,
        health = 100f
    };

    // Act
    object boxedPlayer = playerData; // 装箱为引用类型
    var healthField = typeof(PlayerData).GetField("health");
    healthField.SetValue(boxedPlayer, 75.5f);
    playerData = (PlayerData)boxedPlayer; // 拆箱赋值回原变量

    // Assert
    Assert.AreEqual(75.5f, playerData.health);
}

方案2:使用SetValueDirect直接操作内存(高效但需注意安全)

SetValueDirect可以跳过装箱,直接操作值类型实例的内存,性能更优,但需要正确使用__makeref生成类型引用:

[Test]
public void SetValue_ChangesHealthUsingReflection()
{
    // Arrange
    var playerData = new PlayerData
    {
        name = "Test Player",
        level = 1,
        health = 100f
    };

    // Act
    var healthField = typeof(PlayerData).GetField("health");
    healthField.SetValueDirect(__makeref(playerData), 75.5f); // 直接操作内存

    // Assert
    Assert.AreEqual(75.5f, playerData.health);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:52:08