组件、行为和 MonoBehaviour 有啥区别?为啥这些是分开的?

Posted

技术标签:

【中文标题】组件、行为和 MonoBehaviour 有啥区别?为啥这些是分开的?【英文标题】:What is the difference between Component, Behaviour and MonoBehaviour? And why these are separated?组件、行为和 MonoBehaviour 有什么区别?为什么这些是分开的? 【发布时间】:2017-06-14 09:28:38 【问题描述】:

MonoBehaviour 扩展了 Behavior 和 Behavior 扩展了 Component。 我想知道为什么这些类是分开的以及这些类的语义。 分离这些类有什么目的吗?有没有直接扩展 Behavior 或 Component 的类?

我知道我们必须使用 MonoBehaviour 在 Unity 中创建 C# 代码。 不过,我对 Unity 作为游戏引擎的架构很感兴趣。

【问题讨论】:

如果您不编写Started 和Updated 的代码,则无需继承MonoBehaviour @DmitryPavlushin 嘿,这很有趣,如果我们不需要StartUpdate,我们可以从 Behavior 或 Component 继承吗?我个人尽量避免使用这些(如果可能,我更喜欢事件驱动的代码),所以如果我们可以继承这些,那会是更好的做法吗? @DmitryPavlushin 听起来像是一个答案。 举个例子,您可能有一个预制件,例如包含有关 MB 脚本上预制件的数据。通过预制创建新实例时,您可以访问这些数据并在其上运行一些方法。您可以通过 GetComponent 访问脚本。经常在游戏中你需要访问这些数据,因为假设你的物品是一个会破坏其他物品的弹丸。该脚本可能没有任何开始或更新。因此,第一条评论是错误的。 【参考方案1】:

组件

ComponentBehaviourMonoBehaviour 的基类。它是可以附加到游戏对象的任何脚本的基类。

这几乎是每个 Unity 内置 脚本的来源。这包括ColliderRigidbody


行为

关于Behaviour,最重要的一点是可以启用或禁用从它继承的任何东西。如果您不想启用/禁用它,请不要继承您的脚本。

例如,Rigidbody 无法启用/禁用。这就是为什么它继承自 Component 类而不是 Behaviour

Behaviour 继承自 Component


单一行为

关于MonoBehaviour,最需要注意的是,当你必须使用协程、调用或任何 Unity 回调函数(如物理OnCollisionEnter 函数、StartOnEnable、@987654337)时,你需要它@等

MonoBehaviour 继承自 Behaviour,因此可以启用/禁用您的脚本。

分离这些类有什么目的吗?

是的,就像上面的答案一样,它们是分开的,因此您可以通过从适当的组件继承来使用不同的功能。

您想要协同程序InvokeInvokeRepeating 并能够启用/禁用您的脚本?使用继承自MonoBehaviour

您希望能够启用或禁用脚本但不需要协程InvokeInvokeRepeating?使用Behaviour

当您有一个永远不应启用/禁用的脚本时,它应该继承自 Component

请注意,BehaviourComponent 被 Unity 用于内部内容。你不应该尝试从这些继承你的脚本。

将它们分开的主要原因是为了节省内存,同时也使每个组件中的代码易于维护。这比为一个很少使用的功能编写数千行代码要好。通过分离它们,当它们被加载到内存中时,它们实际上正在被使用,而不是浪费内存中的空间。

有没有直接扩展 Behavior 或 Component 的类?

是的。

MonoBehaviour 直接继承自 Behaviour 然后 继承自Component

Collider 直接继承自 Component。然后是非基础对撞机 比如BoxColliderSphereCollider继承自Collider

【讨论】:

@Programmer “是的,它占用了这么多内存,只有在加载下一个场景时才会释放。”你确定吗?它将一直保留到帧结束,然后将其标记为 GC。如果需要场景加载来清理被破坏的对象,这将是设计的主要缺点。还是您的意思不同? @kyasbal 可能是由于底层 Mono 框架的历史原因。就像所有 Objective-C 类在 NextStep 时都以 NS 开头一样。那么在没有害处的情况下删除前缀就太复杂了。 "注意,行为和组件被 Unity 用于内部的东西。你不应该尝试从这些继承你的脚本。"这与你所说的其他一切相矛盾。当我读到这句话时,听起来你说永远不要从 Behavior 或 Component 继承。是这个意思吗? 我知道这很令人困惑,但是当我说“你”时,我并不是指像你这样的普通程序员。我主要指的是为 Unity 工作的程序员。我还指的是为Unity's UI system 做出贡献的程序员,这是开源的。您将必须了解这些是如何工作的,为什么要使用它们以及何时使用它们中的任何一个才能做出贡献。如果您不是这些人中的任何一个,则不需要使用其中任何一个。 不,您不必将其存储为组件。一旦您在从 MonoBehaviour 创建的另一个类中声明该数据类,您将在 Editor/Inspector 中看到该数据类及其所有变量。它们必须被声明为公共的,或者如果是私有的,则必须具有[SerializeField]

以上是关于组件、行为和 MonoBehaviour 有啥区别?为啥这些是分开的?的主要内容,如果未能解决你的问题,请参考以下文章

verilog的行为级描述和RTL级描述有啥区别

verilog的行为级描述和RTL级描述有啥区别

组件和指令有啥区别?

组件和指令有啥区别?

用户控件、自定义控件和组件有啥区别?

AEM中的parsys组件和响应式布局有啥区别