Unity3d中的c#方法覆盖

时间:2016-06-27 07:59:21

标签: c# unity3d

最近几周,我使用c#作为脚本语言使用Unity3d。 我从来没有在c#和Unity3d之前使用过,我试图理解方法覆盖在Unity框架中是如何工作的。 令我感到奇怪的是,我可以扩展基类MonoBehavior并覆盖诸如Start ()Update ()之类的方法,而不必使用override关键字,编译器也可以不要抱怨它! 取而代之的是#34;正常" C#程序我必须使用override关键字,否则我会收到编译器警告。例如:

public class BaseClass {
    public virtual void MyMethod () {
        Console.WriteLine("BaseClass.MyMethod()");
    }
}

public class SubClass : BaseClass {
    public override void MyMethod () {
        Console.WriteLine("SubClass.MyMethod()");
    }
}

class Program {
    static void Main ()  {
        SubClass obj = new SubClass ();
        obj.MyMethod ();
    }
}

而在Unity中我可以做到:

class PlayerController : MonoBehaviour {
    void Update () {
        // code...
    }
}

幕后会发生什么?团结是否利用"动态技巧"或者什么?

3 个答案:

答案 0 :(得分:17)

因为MonoBehavior没有Update的定义。运行时检查一个名为Update的方法是否存在(使用反射),如果存在,则调用它,但是你没有覆盖基础实现

更新

由于您要求提供有关如何实现这一目标的示例,我已在此处制作了示例:https://dotnetfiddle.net/UrpYkf

答案 1 :(得分:2)

bunny83http://answers.unity3d.com/answers/177292/view.html

来源

  

Unity的工作方式有点不同。所有那些所谓的“事件”都不是   MonoBehaviour类的方法。如果你有C#反射器,你可以   只需打开UnityEngine.dll

即可查看类实现      

Unity主要用c ++编写,因此大多数魔法都发生在   本机代码。在您的脚本之后,Unity使用反射来确定   已编译,您实施的那些“事件”和   记住这个课程。 Unity仅调用Update / LateUpdate /   OnGUI何时实施。

     

您可以注意到的另一点是您创建的时间   MonoBehaviour类并没有实现任何这些方法/事件   Unity将从脚本实例中删除已启用的复选框   因为它不包含受启用影响的任何事件。

     

使用SendMessage函数调度某些事件(如   OnCollisionEnter和此类事件)。

     

文档调用所有事件“Overridable Functions”但是那样   不是真的。如果它们被实现为虚拟功能你   必须使用override关键字,否则它将无效。

     

以下是MonoBehaviour的整个实现:

public class MonoBehaviour : Behaviour
 {
     public extern bool useGUILayout
     {
         get;
         set;
     }
     public extern MonoBehaviour();
     private extern void Internal_CancelInvokeAll();
     private extern bool Internal_IsInvokingAll();
     public extern void Invoke(string methodName, float time);
     public extern void InvokeRepeating(string methodName, float time, float repeatRate);
     public void CancelInvoke();
     public extern void CancelInvoke(string methodName);
     public extern bool IsInvoking(string methodName);
     public bool IsInvoking();
     public Coroutine StartCoroutine(IEnumerator routine);
     public extern Coroutine StartCoroutine_Auto(IEnumerator routine);
     public extern Coroutine StartCoroutine(string methodName, object value);
     public Coroutine StartCoroutine(string methodName);
     public extern void StopCoroutine(string methodName);
     public extern void StopAllCoroutines();
     public static void print(object message);
 }
  

我几乎每次都删除了所有外部属性   方法/属性映射到本机函数。

     

顺便说一句。提到的C#事件是委托,它们只是某种形式   函数指针,但有点复杂;)

答案 2 :(得分:1)

在MonoBehaviour基类中没有声明Start,Update,Awake等。这就是您在声明它们时不写任何Override关键字的原因。如果Unity3D在您的课程中实现,它们将被调用,这可以提高性能。