检查员引用的Unity枚举在扩展时会出现故障

时间:2014-10-03 09:18:56

标签: c# serialization enums unity3d

问题:

当枚举在引用的索引之前添加了新条目时,游戏对象脚本通过检查器变量引用的枚举变得乱序。

详细说明:

所以我有多个系统,如项目列表,本地化字符串等,它们是通过解析外部文件动态构建的。此解析创建枚举,用于通过脚本检查器变量通过游戏对象引用项目。以下是我的本地化系统的解析输出作为示例:

    public enum LocaleID 
    {
        LocalisedStrings_ENGB,
        LocalisedStrings_ENUS,

        //...

        MAX,
    }

    public enum StringID 
    {
        String_EMPTY,
        String_Inventory,
        String_Recipes,
        String_Tools,
        String_Journal,

        //...
    }

public static class LocalisedStrings
{
    private static string[] SCLocalisedStrings_ENGB = 
    {
        "",
        "Inventory",
        "Recipes",
        "Tools",
        "Journal",

        //...
    }

    private static LocaleID currentLocale = (LocaleID)0;
    private static string[] activeSC = SCLocalisedStrings_ENGB;

    public static void SetLocale(LocaleID newLocale)
    {
        currentLocale = newLocale;
        switch(newLocale)
        {
            case LocaleID.LocalisedStrings_ENGB:
                activeSC = SCLocalisedStrings_ENGB;
            break;
            case LocaleID.LocalisedStrings_ENUS:
                activeSC = SCLocalisedStrings_ENUS;
            break;
        }
    }

    //entry interface: 
    public static string Get(StringID stringID)
    {
        return activeSC[(int)stringID];
    }
}

这只是根据set locale通过枚举索引返回字符串。 所以我会在角色上暴露一些NPC的名字:

[SerializeField]
public StringID SpeakerTitle;

并通过检查员设置。

问题是一个相当明显和预期的问题 - 如果枚举的解析方式不同,例如在顶部添加额外的条目(例如用于排序)或删除(用于清理过时的条目),则所有引用枚举将失去1个点,因为它们将引用枚举条目的索引。

一个简单的解决方案是强加一条规则,只添加到最后,永远不会删除过时的条目。这变得非常浪费,所以显然不是很好。

此问题的建议解决方案是什么?其他人如何处理这种相当常见的情况的例子?我的偏好当然是可以排序的东西,新的条目可以添加到任何地方,但我们不能拥有我们想要的一切:)

2 个答案:

答案 0 :(得分:1)

只需为条目指定显式数值:

public enum StringID 
{
    String_EMPTY = 0,
    String_Inventory = 1,
    String_Recipes = 2,
    String_Tools = 3,
    String_Journal = 4,

    //...
}

这样,排序完全与值无关。请注意,您可以追溯或以“及时”的方式执行此操作,当您需要进行本来会发生重大变化时。

(我个人也会删除String_前缀,但这是另一回事。)

答案 1 :(得分:0)

我会使用显式地图而不是裸数组;例如:

private static Dictionary<StringID,string> SCLocalisedStrings_ENGB = 
    new Dictionary<StringID,string>
{
    {StringID.String_EMPTY, ""},
    {StringID.String_Inventory, "Inventory"},
    //...
};

并通过以下内容获取价值:

string val;
return LocaleStrings.TryGetValue(key, out val) ? val : DefaultStrings[key];

嗯......实际上,我可能将外部文件中的翻译作为键/值对,但是...... meh。

注意:您始终字典数据放回有序数组中;但是拥有明确的地图会阻止订单生效。