С# метод переопределения в Unity3d

В последние недели я играл с Unity3d, используя С# в качестве языка сценариев. Я никогда не использовал до С# или Unity3d, и я пытаюсь понять, как методы переопределяют работу в Unity framework. Меня удивляет, что я могу расширить базовый класс MonoBehavior и переопределить методы, такие как Start (), Update () и т.д., Не используя ключевое слово override, и компилятор не жалуется на это! Вместо этого в "нормальной" программе С# я должен использовать ключевое слово 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...
    }
}

Что происходит за кулисами? Использует ли единство "динамические трюки" или что?

Ответы

Ответ 1

Потому что MonoBehavior не имеет определения для Update. Время выполнения проверяет, существует ли метод с именем Update (с использованием отражения), а затем вызывает его, если это так, но вы не переопределяете базовую реализацию

Update

Поскольку вы попросили пример о том, как это было возможно, я сделал образец здесь: https://dotnetfiddle.net/UrpYkf

Ответ 2

Источник bunny83 в http://answers.unity3d.com/answers/177292/view.html

Unity работает немного иначе. Все эти так называемые "события" НЕ методы класса MonoBehaviour. Если у вас есть рефлектор С#, вы можете просто просмотрите реализацию класса, открыв UnityEngine.dll

Единство в основном написано на С++, и поэтому большинство магов происходит в собственный код. Unity использует рефлексию для определения, после ваших скриптов были составлены, какие из этих "событий" вы внедрили и помните, что для этого класса. Unity только вызывает Update/LateUpdate/ OnGUI, когда он был реализован.

Еще один момент, когда вы можете заметить, что это когда вы создаете MonoBehaviour и не применяйте ни один из этих методов/событий Unity удалит установленный флажок с вашего экземпляра scriptпотому что он не содержит никаких событий, на которые влияет включенное.

Некоторые события отправляются с помощью функции SendMessage (например, OnCollisionEnter и такие события).

Документация вызывает все события "Переопределяемые функции", но это не правда. Если они были реализованы как виртуальная функция, вы должен был бы использовать ключевое слово 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);
 }

Я удалил все внешние атрибуты, поскольку почти каждый метод/свойство отображается на нативную функцию.

кстати. упомянутые события С# являются делегатами, которые являются лишь своего рода функциональные указатели, но немного сложнее;)

Ответ 3

В базовом классе MonoBehaviour не указаны "Пуск", "Обновление", "Пробуждение" и т.д. Вот почему вы не пишете ключевое слово Override при их объявлении. Они будут вызываться Unity3D, если они реализованы в вашем классе, что может привести к повышению производительности.