Actor/Component 与 entity/component:同名不同物
两边都有一个词叫「组件」,含义却差得很远。蓝图的世界是一棵继承树:Actor 靠派生子类长出功能,组件是它的配件。Scene Graph 的世界是组合:entity 几乎是个空壳,组件就是全部。这一页讲清这两种模型的根本差别,顺便给第八章埋个伏笔。
一、先对齐一下状态
免得读到一半误会,先把事实摆清楚:
Scene Graph 是 Epic 为 UE6 打造的新玩法框架,从零基于 Verse 构建,用 entity(实体)装 component(组件),今天已经可以在 UEFN 中使用。同时,Actor 与 Blueprint 在 UE6 Early Access(目标 2027 年底)及早期版本中完整支持;弃用要等 Scene Graph 足够成熟,时间未定。Epic 已承诺在弃用前提供转换工具,但尚未发布。
所以这一页不是「学新的、扔旧的」。它要解决的是一个更实际的问题:当两套体系并存、而且共用「组件」这个词的时候,别把它们当成一回事。
二、继承树模型:Actor 是怎么长出功能的
回想你做过的项目。一扇门:BP_Door。要一扇会上锁的门:右键 BP_Door → Create Child Blueprint Class → BP_LockedDoor。要一扇会上锁、还会在开的时候放特效的门:再派生一层。功能是从上往下继承来的:子类自动拥有父类的一切,再往上加一点自己的。
这套模型的好处很直观:BP_LockedDoor 一定「是一扇门」,它能被任何接受门的地方接受。麻烦也很直观 —— 你迟早会遇到这样的需求:「我想要一扇会发光的门,还想要一个会发光的箱子」。发光这段逻辑该放哪儿?放进 BP_Door,箱子用不上;放进两边各一份,以后改一处忘一处;提到公共父类里,那个父类就会慢慢胖成一个什么都有的怪物。继承树只有一根主干,而需求是横着长的。
Actor Component 正是为了缓解这个问题而存在的:把「发光」做成一个组件,门和箱子各装一个。但请注意 —— 在蓝图的世界里,这只是两条路里的一条。Actor 本身仍然是一个可以被派生的类,逻辑既可以写在 Actor 上,也可以写在 Component 上,两种写法长期并存。于是每个团队都要反复争论一次「这段逻辑该放 Actor 还是放 Component」。
三、组合模型:entity 是空壳,component 才是内容
Scene Graph 把这个问题一刀切掉了:只留下组件这一条路。
entity 是关卡里的一个节点,自己几乎没有行为 —— 它有身份、有变换、有父子关系,然后就没了。它不是给你派生的:你不会写「一个继承自 entity 的门实体」。想让它成为一扇门,你往上装组件:一个负责网格外观、一个负责交互、一个负责开合状态。
于是「这个东西是什么」这个问题,答案从「它继承自哪个类」变成了「它装了哪些组件」。会发光的门和会发光的箱子?各装一个发光组件,完事 —— 没有共同父类,也不需要有。
组件本身就是一个 Verse 类,长得和你在第 6 课要写的设备类很像:有 @editable 字段(会出现在 Details 面板里)、有生命周期入口。下面这段只展示形状,让你有个直观印象 —— Scene Graph 的具体接口仍在演进,以官方文档与第八章为准:
using { /Verse.org/Simulation }
# 组件是一个 Verse 类,装在某个 entity 上
spinner_component := class(component):
@editable
DegreesPerSecond:float = 90.0
OnBegin<override>()<suspends>:void =
loop:
# 每帧转一点(变换相关的接口见第八章)
Sleep(0.0)
把这个组件装到门上,门会转;装到箱子上,箱子会转;装到一盏灯上,灯会转。它不需要知道自己装在什么上面 —— 这正是组合模型省事的地方。
四、同一个词,五个不同
把两边的「组件」摆在一起看:
| 问题 | 蓝图:Actor + Actor Component | Scene Graph:entity + component |
|---|---|---|
| 宿主是什么 | 一个可以被派生的 Actor 子类,自己就有大量功能 | 一个几乎没有行为的 entity,只有身份、变换与父子关系 |
| 逻辑写在哪 | Actor 上、Component 上都行,两条路并存 | 只有组件一条路 |
| 怎么加功能 | 派生一个子类,或者装一个组件 | 装一个组件 |
| 「它是什么」由谁回答 | 由继承链回答:它是一个 BP_LockedDoor,所以它是一扇门 |
由组件清单回答:它装了交互组件和开合组件,所以它像一扇门 |
| 用什么写 | C++ 或蓝图节点图 | Verse —— 这套框架本身就是从零基于 Verse 构建的 |
看第四行。这是最容易被忽略、也最要命的一条:继承模型里「是什么」是一个身份,编译器帮你保证;组合模型里「是什么」是一个观察结果,取决于当下装了哪些组件,而组件是可以增减的。这不是哪个更好的问题,是两种回答方式,写代码时的思路完全不同。
五、这对你意味着什么
第一,读文章时先看年份和用词。一篇讲 UEFN Verse 的教程,通篇 creative_device、没有 entity 与 component,那它讲的是今天能跑的写法,没问题,但它没覆盖 Scene Graph。反过来,满篇 entity/component 的文章,讲的是 UE6 的方向。两者今天都成立,别把其中一篇当成全部。
第二,现在就可以练习「拆组件」的思维。不需要等 UE6。打开你手上任何一个塞满逻辑的 Actor 蓝图,拿张纸把它拆成三到五块互不依赖的功能 —— 这块管移动、这块管血量、这块管特效触发。拆得出来的项目,将来迁移时几乎是体力活;拆不出来的,继承树上那一大坨才是真正的麻烦。
第三,别急着改造现有项目。Actor 与 Blueprint 在 UE6 Early Access 及早期版本中完整支持,Epic 已承诺提供转换工具但尚未发布。在工具落地之前,提前手工重构的收益远小于风险。你现在要投资的是理解,不是返工。
组合优于继承这件事,以及 Scene Graph 完整的世界观,是第八章的主题。到那里我们会真的写一个组件。
六、小测验
在 Scene Graph 里,「这个东西是什么」由什么决定?
来源
本文整理自 Epic 官方文档:Blueprints Visual Scripting(官方文档)↗ · Verse Language Quick Reference(官方文档)↗
UE6、Scene Graph 与蓝图弃用时间线的表述,以 Epic 在 State of Unreal 2026 的公开说明与官方路线图为准:UE6 Early Access 目标 2027 年底,Actor 与 Blueprint 在 EA 及早期版本中完整支持,转换工具已承诺但尚未发布。