如何在Unity的检查器中编辑键值对(例如字典)?


18

我有一个正在创建的咒语系统,原理如下:

  • 每个咒语都是一个自主的预制件。它包含具有某些属性(基本损坏,持续时间...)的脚本,可以在检查器中对其进行修改。
  • 我有一个Spell枚举,列出了代码中所有可能的咒语,用于游戏逻辑
  • 当我想施放法术时,我需要能够获得该法术的预制件以实例化它并读取其信息。
  • 每个演员(无论是玩家还是敌人)都需要列出该咒语的可能动画

我尝试实现的问题是:

  • 为了列出每个演员的动画,我可以使用Dictionary<Spell, Animation>,但是检查器不支持字典,这使得很难轻松地编辑多个演员类型。
  • 我需要一些方法来轻松地从相应的枚举中访问拼写预制件。在这里我也可以使用字典,但是我只能在检查器中引用预制件,而不能在代码中引用,这意味着我将无法填充此字典

我正在寻找一种将我的咒语枚举轻松关联到相应的预制件和动画的方法


1
我是否可以建议更改此问题的标题以引用在Unity检查器中获得类似字典的行为(映射键值对)?这将有助于使其他拥有或正在寻找解决此类问题的想法的用户更容易找到问题。即使这种特定情况是关于咒语的,相同的技术也更广泛地适用。
DMGregory

@DM我不了解Unity,但是您的一般推理听起来很明智。大胆地编辑 回滚很便宜。
Anko 2014年

Answers:


24

在Unity检查器中获取键-值对的一种快速方法是定义一个可序列化的入口类,然后使用它们的数组或List <>。例如...

public class SpellAnimationMap : ScriptableObject
{
   [System.Serializable]
   public class SpellAnimationEntry
   {
       public Spell spell;
       public AnimationClip animation;
   }

   public SpellAnimationEntry[] spellAnimations;    
}

这将自动为您提供检查器中可调整大小的列表,您可以在其中输入键和值,而无需编写自定义检查器。

结果看起来像这样:

自动生成的检查器

(一个技巧:如果序列化的入口类包含一个“名称”字段,将显示该字符串,而不是平淡的“元素0”标题。如果您要处理更复杂的数据,则很有用。)

将其设置为ScriptableObject可使您将其视为需要相同动画集的实体类型/实例之间共享的资产,从而避免了为每个实体/列表重复副本的开销。(其他类倾向于在Unity中按实例序列化)。要走这条路,您需要添加一个小的编辑器脚本,以使您可以在Assets文件夹中创建这些脚本的实例


编辑:现在更容易- 您可以在ScriptableObject上方添加此属性

[CreateAssetMenu(fileName = "fileName.asset", menuName = "Some Folder/Menu Label")]

这会将ScriptableObject放入“创建”菜单,如下所示: 屏幕快照显示了Unity中的自定义“创建”菜单


您可以选择将数组设置为私有并进行序列化,以使其仍显示在检查器中,但可以添加公共词典(或具有公共GetAnimation(Spell spell)方法的私有词典)供客户端使用,以进行更有效的查找。在其OnEnable()方法中,SpellAnimationMap可以遍历其检查器填充的数组以一次构建此字典,从而再次在所有客户端实例之间共享收益。(请注意,首次创建资产时,也会在编辑器中调用OnEnable(),因此请确保在尝试读取数组之前检查数组是否为空)

最后,您可以根据需要在此条目数据类型中添加尽可能多的内容。例如,它也可以包括预制件,或者您想要链接到拼写键的任何其他数量的数据。

也可以编写自定义检查器来直接填充Dictionary <,>字段,但是我得到的印象是顺利进行工作很麻烦。


究竟是什么,我碰巧在等待一个答案的事,所以,我会接受这一个
Malharhak

0

阅读@DMGregory提供的说明

对于那些喜欢示例的人:

public class SpellHandler : ScriptableObject
{
    public Spell[] keys;
    public Animation[] values;

    private Dictionary<Spell, Animation> dic;

    void Awake()
    {
        int length = keys.Length;
        this.dic= new Dictionary<Spell, Animation>(length);
        for (int i = 0; i < length; i++)
        {
            this.dic.Add(keys[i], values[i]);
        } 
    }    
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.