(UNITY / C#) 没有从派生的泛型类调用重写的函数

问题描述

我知道有很多关于虚拟/覆盖函数、操作方法和文档的问题得到解答,但我还没有找到与我想要完成的任务相匹配的内容

我正在开发一个系统,通过我在 Unity 中创建的编辑器窗口创建数据对象(专门用于具有 RPG 元素的游戏)。我一切都很好,正如预期的那样,但后来我决定尝试使用泛型将每个管理面板中的所有代码压缩到一个类中。

我对泛型还是很陌生,但从我迄今为止的试验来看,它的效果如我所愿。现在唯一的问题是,由于某种原因,当我尝试从派生类调用 Draw 方法时,它改为使用父类的虚拟方法。我以前从未见过这种情况,也许我是瞎子,我在这里遗漏了一些东西,或者这可能是泛型使用的特定问题。

public class DataManagementPanel<T> where T : DataObject {
   public static DataManagementPanel<T> instance;
   public static DataManagementPanel<T> GetInstance() {
      if (instance == null) {
         instance = new DataManagementPanel<T>();
      }
      return instance;
   }

   protected virtual void Draw(Rect window) {
      Debug.Log("Calling Base Class");
   }
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   protected override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}

此外,我有一个 DataObject 类,用于保存基本信息和 ClassData 的派生类,用于保存特定于 RPG Class/Job 系统的数据,以及一个派生的 FactionData 类,用于保存特定于游戏派系系统的数据。

>
public class DataObject {
   public int ID;
   public string Name;
}

public class ClassData : DataObject {
   public string IconPath;
}

public class FactionData : DataObject {
   public int Reputation;
}

最后,我试图在另一个类中找到的 OnGUI() 函数中的我的编辑器窗口上绘制管理面板。控制台输出返回“调用基类”,而不是预期的“调用派生类”。

public class ManagementPanelEditorWindow : EditorWindow {
   void OnGUI() {
      ClassManagementPanel.GetInstance().Draw(position);
   }
}

解决方法

我找到了一个似乎对我有用的修复程序。与其尝试在 DataManagementPanel 类中拥有一个静态实例,不如将其设为抽象类并将静态实例移至每个单独的面板类。

public abstract DataManagementPanel<T> where T : DataObject {

   public abstract Draw(Rect window);
}

public ClassManagementPanel() : DataManagementPanel<ClassData>() {
   
   private static ClassManagementPanel instance;
   public static ClassManagementPanel GetInstance() {
      if (instance == null) {
         instance = new ClassManagementPanel();
      }
      return instance;
   }       

   public override void Draw(Rect window) {
      Debug.Log("Calling Derived Class");
   }
}

此更改会产生所需的“调用派生类”输出,更具体地说,可以按预期在编辑器窗口中绘制我的面板。