@editable 引用:把关卡里的对象接进代码
蓝图里勾一下 Instance Editable,再在 Details 面板拖一个 Actor 进去,代码就拿到了关卡里的对象。Verse 用 @editable 做同一件事,但多了几条规矩:默认值必须给、数组插槽怎么用、能不能引用你自己写的类,以及重命名字段会踩的雷。
一、Object Reference 变量 ↔ @editable 字段
这两件事是逐字对应的:
| 蓝图 | Verse | 差异 |
|---|---|---|
| 变量面板新建变量,类型选某个 Actor 类的 Object Reference | TriggerButton:button_device |
类型写法不同,含义一样:一个「指向关卡里某个对象」的字段 |
| 勾上 Instance Editable(那只眼睛) | 字段上方独占一行的 @editable |
蓝图是勾选框,Verse 是属性;两者都只是「让它出现在面板上」 |
| 默认值是 None | = button_device{},必须写 |
Verse 不接受「空着」这个状态;漏写默认值直接 Compile 报红 |
| Details 面板下拉框里挑一个关卡 Actor | 同一个 Details 面板,拖进这个插槽 | 完全一致,这一步没有代码替代品 |
最需要适应的是第三行。蓝图里对象引用天然可以是 None,于是你养成了「用之前 Is Valid 一下」的肌肉记忆;Verse 把这条路堵死了——字段必须初始化成一个空原型,类型系统里不存在「这里可能是空的」。
但要说清楚一件事:这不等于「面板不连线也没事」。空原型只是让代码能编译,它不是关卡里那个真实对象。面板忘了拖线,进游戏碰它就是运行时错误。Verse 消灭的是「忘了判空」这类失误,没消灭「忘了配置」——后者永远是人的责任,蓝图那边也一样。
二、数组插槽:一次拖一批
蓝图里你会把变量类型改成 Array of Actor Reference,面板上就出现一个可以 + 添加元素的列表。Verse 同理:
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
# 被通知方:暴露一个 public 函数当「收件口」
siren_device := class(creative_device):
OnNotified<public>():void =
Print("收到广播,警笛拉响!")
# 通知方:面板上拖进一批警笛,广播时挨个点名
notifier_device := class(creative_device):
@editable
Listeners:[]siren_device = array{}
Broadcast<public>():void =
for (L : Listeners):
L.OnNotified()
读图翻译:[]siren_device 就是「一个装 siren 设备引用的数组」,默认值是空数组 array{};进编辑器后在面板上把关卡里的每台警笛拖进这个列表。Broadcast 用一个 ForEach 遍历列表,挨个调用它们暴露出来的 OnNotified。
这是最直白的「一对多」做法,和第 25 课主课里的 event(t) 是两条不同的路:数组是点名式(通知方认识每一个听众,顺序可控),事件是广播式(发布方谁也不认识)。两者的取舍:
| 方式 | 耦合度 | 适合场景 |
|---|---|---|
@editable 单个引用,直接调它的 <public> 函数 |
高:甲必须认识乙 | 一对一、关系固定的两个对象 |
@editable 数组,ForEach 点名 |
中:名单在面板上,顺序可控 | 听众数量固定、需要确定顺序 |
共享 event(t),Signal / Subscribe |
低:发布方不认识任何人 | 跨模块解耦、听众会增删 |
经验法则和你在蓝图里的一样:能用事件解耦就用事件;只有当你确实需要「按面板上的顺序逐个通知」或「运行时读得到这份名单」时,数组插槽才更合适。
三、引用你自己写的类
@editable 不只能引用原生设备,也能引用你自己写的 Verse 类——上面那个 Listeners:[]siren_device 就是例子,主课里 gate_device 引用 starter_device 也是。这相当于蓝图里把变量类型选成你自己那个 BP_Siren 类。
两条附加规则值得记住:
- 被引用的成员必须标
<public>,外面才访问得到。蓝图里对应的是节点上那个 Public / Private 开关,只是 Verse 默认更保守。 - 如果你想把一个普通类(不是设备)整个摆上面板当可配置数据用,那个类需要
<concrete>标记,条件是它的每个字段都有默认值——道理和@editable字段必须有默认值是同一条:面板上不能出现「还没决定」的格子。
四、面板与代码之间的两个雷
雷一:改了代码,面板没变化。新加的 @editable 字段不会自己出现——要先把 Verse 代码重新构建 / 推送到编辑器。这一步相当于蓝图里点 Compile:不点,面板不会刷新。
雷二:重命名字段可能让已配置的引用丢失。面板上的配置是按字段名存的,改名之后旧配置可能对不上,表现为「面板上那一格突然空了」。蓝图里改变量名有重定向机制兜着,Verse 这边没有同等保障,所以改名之后务必回编辑器逐个检查插槽。这两条合起来,就是「代码全对、进游戏就炸」这类事故最常见的两个上游原因。
下面这个字段为什么 Compile 不过?@editable 换行后写 Door:barrier_device
来源
本文整理自 Epic 官方文档与开发者论坛: