代码之家  ›  专栏  ›  技术社区  ›  Get Off My Lawn

调用虚拟方法而不是重写

  •  2
  • Get Off My Lawn  · 技术社区  · 8 年前

    我有四节课, Event Action 都是基类,然后我有两个子类 Create : Event MoveTo : Action .

    事件 实例,以及何时 Trigger() 孩子被叫来了 Create 它叫 Event.Trigger() Action.Run() 每一个动作 Called() .

    我遇到的问题是 virtual 方法被调用,而不是 override 方法内部 MoveTo

    [Serializable]
    public abstract class Event : MonoBehaviour {
      [SerializeField] public List<Action> actions = new List<Action>();
    
      protected void Trigger() {
        foreach (Action action in actions) {
          action.Run();
        }
      }
    }
    

    事件

    public class Create : Event {
      void Start() {
        Trigger();
      }
    }
    

    行动

    [Serializable]
    public class Action {
      public virtual void Called() {
        Debug.Log("Virtual");
      }
    
      public void Run() {
        Called();
      }
    }
    

    public class MoveTo : Action {
      public override void Called() {
        Debug.Log("Called");
      }
    }
    

    我正在添加

    private Event GetCurrentEvent(){}
    
    void AddActionCallback(Type actionType) {
      // actionType is MoveTo
      var prefab = GetCurrentPrefabItem().Value;
      var evt = GetCurrentEvent();
      evt.actions.Add((Action)Activator.CreateInstance(actionType));
      Undo.RecordObject(prefab.gameObject, "Added actions");
      PrefabUtility.RecordPrefabInstancePropertyModifications(prefab.gameObject);
    }
    

    这是我玩游戏前的样子。它显示了 移动到 ,红色列中的按钮显示使用 action.GetType().Name . 这是我运行游戏之前的名称:

    before

    在我运行游戏后,按钮现在看起来像这样:

    after

    运行时:

    evt.actions.Add((Action)Activator.CreateInstance(actionType));
    

    编辑器显示 类型不匹配 即使 actionType 和 Activator.CreateInstance(actionType) 是 移动到 :

    type mismatch

    1 回复  |  直到 8 年前
        1
  •  1
  •   Ruzihm aks786    8 年前

    Unity does not support built-in polymorphic serialization .

    Action s、 并删除所有只有子类 MoveTo 有。

    来自团结 docs on serialization :

    不支持多态性

    如果你有 public Animal[] animals 你把一个 Dog ,一个 Cat 和一个 Giraffe ,之后 序列化时,有三个 Animal .

    处理这种限制的一种方法是认识到 应用于内联序列化的自定义类。引用 其他 UnityEngine.Objects ScriptableObject 派生类或其他 MonoBehaviour 并引用它。这样做的缺点是需要存储 那个 Monobehaviour 或 scriptable 在某个地方反对,而你不能 有效地内联序列化。

    这些局限性的原因是 类的字段,而不是 领域。

    这就是为什么它的类显示为 .

    但是,它不能序列化为 because :

    如何确保自定义类可以序列化

    • 具有可序列化属性

    • 不是抽象的

    • 不是静态的

    • 不是泛型的,尽管它可以从泛型类继承

    行动 Type Mismatch 问题,因为Unity正在努力反序列化一些不受支持的内容。

    简而言之,如果您想在 移动到 ,你需要有一个 [SerializeField] List<MoveTo> 为了不丢失信息,或者您可以从 脚本化对象 ,这也带来了自身的问题。