序列化枚举字段时枚举索引错误 (Unity)

Wrong Enum index when serializing an Enum field (Unity)

在 Unity3D 中,我有两个枚举:

public enum GlobalColor
{
    Player,
    PlayerFX1,
    PlayerFX2,
    Ennemy,
    EnnemyFX1,
    EnnemyFX2,
    Background,
    BackgroundParticles1,
    BackgroundParticles2,
    Button,
    InactiveButton
}
public enum ColorName
{
    Player,
    PlayerFX1,
    PlayerFX2,
    Ennemy_1,
    EnnemyFX1_1,
    EnnemyFX2_1,
    Ennemy_2,
    EnnemyFX1_2,
    EnnemyFX2_2,
    Ennemy_3,
    EnnemyFX1_3,
    EnnemyFX2_3,
    Background,
    BackgroundParticles1,
    BackgroundParticles2,
    Button,
    InactiveButton
}

ColorName 用于创建调色板(每个 Enum 元素对应于我游戏中的特定颜色),GlobalColor 用于将颜色附加到 GameObjects,Ennemy 只出现一次,因为敌人的颜色是在三个中随机选择的颜色名称。 在一个通用的 ColoriseBase 脚本中(它是所有 Colorise 脚本的基础,负责根据当前调色板的颜色为不同的组件着色,存在 ColoriseSprite、ColoriseParticleSystem 和 ColoriseCamera,它们都继承自 ColoriseBase)我有以下代码: [SerializeField] private GlobalColor color; 能够直接在检查器中选择我的组件的颜色。 要将此 GlobalColor 转换为 ColorName(以在当前调色板中找到正确的颜色),我正在使用反射:

protected ColorName GlobalColorToColorName(GlobalColor color)
{
    string randomEnnemy = "";
    if (color == Ennemy || color == EnnemyFX1 || color == EnnemyFX2)
    {
        EnnemyIdentity ennemyIdentity = GetComponentInParent<EnnemyIdentity>();
        if (ennemyIdentity != null)
            randomEnnemy = string.Format("_%s", ennemyIdentity.EnnemyType.ToString());
        else
            throw new MissingComponentException("An ennemy needs to have an EnnemyIdentity script attached to it.");
    }
    print(Enum.GetName(typeof(GlobalColor), color));
    string name = Enum.GetName(typeof(GlobalColor), color);
    var type = typeof(ColorName);
    return (ColorName)type.GetProperty(name + randomEnnemy).GetValue(null);
}

打印方法用于调试目的。但是,当我启动我的游戏时抛出异常:

NullReferenceException: Object reference not set to an instance of an object
ColoriseBase`1[E].GlobalColorToColorName (GlobalColor color) (at Assets/Scripts/Color/ColoriseBase.cs:56)
ColoriseBase`1[E].get_Color () (at Assets/Scripts/Color/ColoriseBase.cs:10)

我试图找到错误,我发现我的变量 GlobalColor colorin ColoriseBase 不等于我在检查器中给出的值。如果在检查器中我在 Player(which index == 0) 初始化它,这个变量将有索引 12,GlobalColor 的成员没有这个索引,这会导致异常。

不是 100% 但很确定错误来自

type.GetProperty

因为你的类型是 enum 它没有属性,它只有值。很可能这个 returns null 以及后来的 GetValue 导致异常。

您可能更愿意使用 Enum.Parse<TEnum>(string),例如(假设其余部分按预期工作)

return Enum.Parse<ColorName>(name + randomEnnemy);

对于以后的问题和问题:请指出异常是从哪一行抛出的。

一般来说,出于调试目的,请避免像您在

中那样进行更长的链式访问
return (ColorName)type.GetProperty(name + randomEnnemy).GetValue(null);

将所有内容都放在一行中,您将一无所获,好吧,除非如前所述,调试它会更糟。你也可以写成

var fullName = name + randomEnnemy;
var property = type.GetProperty(fullName);
return (ColorName) property.GetValue(null);

但是这样你可以更好地调试 Debugging your code with breakpoints

谢谢 derHugo 我找到了解决办法,这是我的新 GlobalColorToColorName 方法:


protected ColorName GlobalColorToColorName(GlobalColor color)
{
    string name = color.ToString();
    if (color == Ennemy || color == EnnemyFX1 || color == EnnemyFX2)
    {
        string randomEnnemy;
        EnnemyIdentity ennemyIdentity = GetComponentInParent<EnnemyIdentity>();
        if (ennemyIdentity != null)
            randomEnnemy = string.Format("_%s", ennemyIdentity.EnnemyType.ToString());
        else
            throw new MissingComponentException("An ennemy needs to have an EnnemyIdentity script attached to it.");
        name += randomEnnemy;
    }
    return (ColorName)Enum.Parse(typeof(ColorName), name);
}