序列化枚举字段时枚举索引错误 (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 color
in 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);
}
在 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 color
in 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);
}