unity游戏引擎- c#方法覆盖Unity3d
本文关键字:方法 覆盖 Unity3d 游戏 引擎 unity | 更新日期: 2023-09-27 17:51:21
最近几周,我使用c#作为脚本语言来玩Unity3d。我从来没有使用过c#和Unity3d之前,我试图了解方法重写如何在Unity框架的工作。让我感到奇怪的是,我可以扩展基类MonoBehavior
并覆盖Start ()
, Update ()
等方法,而不必使用override
关键字,编译器也不会抱怨它!相反,在"正常"的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...
}
}
幕后发生了什么?unity是否使用了"动态技巧"?
因为MonoBehavior
没有Update
的定义。运行时检查一个名为Update
的方法是否存在(使用反射),如果存在,则调用它,但您没有覆盖基本实现
既然你要求一个例子来说明这是如何可能的,我在这里做了一个例子:https://dotnetfiddle.net/UrpYkf
来源 by bunny83 at http://answers.unity3d.com/answers/177292/view.html
Unity的工作方式有点不同。所有那些所谓的"事件"都不是MonoBehaviour类的方法。如果你有一个c#反射器,你可以通过打开UnityEngine.dll 查看类实现Unity主要是用c++编写的,因此大多数神奇的事情发生在本机代码。Unity使用反射来确定脚本之后编译完成后,你实现了哪些"事件"记住这堂课。Unity只调用Update/LateUpdate/OnGUI,当它已经实现。
您可以注意到的另一点是创建MonoBehaviour类,并且不实现任何这些方法/事件Unity将从你的脚本实例中移除enabled复选框因为它不包含任何受启用影响的事件。
一些事件是用它们的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);
}
我几乎每次都删除了所有的外部属性方法/属性映射到本机函数。
顺便说一句。上面提到的c#事件是委托,它只是某种函数指针,但有点复杂;)
在MonoBehaviour基类中没有声明Start, Update, Awake等。这就是为什么在声明Override关键字时不需要编写它们的原因。如果在你的类中实现它们,它们将被Unity3D调用,这可以导致性能改进。