Verse Wiki — 写给蓝图作者的 Verse 手册
技巧 · EXTRA

@editable 与 Details 面板:让美术也能改你的组件

一个只有程序能改的组件是半成品。@editable 把字段送进 Details 面板,让策划和美术自己调参。这一页把它讲透:能暴露哪些类型、怎么加滑块和数值上下限、怎么分组和写悬浮提示,以及默认值与关卡里的覆盖值到底谁说了算。

一、写在哪、意味着什么

@editable 是一个属性(attribute):以 @ 开头,单独占一行,写在被它修饰的字段上面。这一点和 <public><final_super> 那种夹在尖括号里的说明符(specifier)是两套语法,别混。

lift_platform_component.verse
lift_platform_component<public> := class<final_super>(component):

    @editable
    Height<public>:float = 200.0
#   ▲          ▲       ▲      ▲
#   属性       可见性   类型   默认值(必须有)

加上它之后发生三件事:这个字段出现在 UEFN 的 Details 面板里;代码里写的那个值成为面板里的初始显示值;把这个组件装到不同 entity 上时,每一份都能填不同的值。官方文档对最后一条的表述很直白:改一个可编辑属性的值,只对该实例生效——同一个组件在关卡里有五份,五份可以各不相同。而且改面板不需要重新编译

这三条合起来,恰好就是蓝图 Instance Editable 的全部语义。你在蓝图变量旁边点亮的那只小眼睛,在 Verse 里变成了一行字。

反过来说:不加 @editable 的字段是纯内部数据,面板里根本看不到。这也是一条设计纪律——只把「真正需要别人调」的东西暴露出去,别把内部状态一股脑摊在面板上,否则策划面对二十个不知道能不能动的格子,只会来问你。

二、能暴露哪些类型

官方文档给出的可编辑类型清单如下。注意「容器和结构体」那一档有个递归条件:里面装的东西也得是可编辑的,否则整个字段都进不了面板。

档次 类型 面板里长什么样
基础类型 logicintfloatstringenum 勾选框、数字输入框、文本框、下拉列表
容器 可编辑类型的 arraymap 可增删的列表 / 键值对列表
结构体 字段全部可编辑的 struct 一个可展开的分组
类实例 类的实例(包括设备类型) 一个可指向场景中对象的引用槽

把这张表和蓝图变量面板的 Variable Type 下拉对照着看,覆盖面几乎重合:布尔、整数、浮点、字符串、枚举、数组、映射、结构体、对象引用——蓝图里能勾 Instance Editable 的东西,Verse 这边基本都能标 @editable

「类实例」那一档最像蓝图里的「Actor 引用变量」:在蓝图里你会声明一个 Target Door 变量、类型选某个蓝图类,然后在关卡里用滴管吸一个具体的门。Verse 这边写法是给字段一个类实例的默认值,面板里就会出现同样的引用槽。

三、变体:给格子加护栏

@editable 给出的是一个不设防的输入框——策划可以把 Height 填成 -99999。蓝图里你会在变量的 Details 里设 Slider Range 和 Value Range;Verse 这边则是换用一个更具体的属性变体。官方文档列出的主要变体如下:

变体 用途 蓝图对应
@editable_number(类型) 带 MinValue / MaxValue 的数值输入框 变量 Details 里的 Value Range
@editable_slider(类型) 带上下限和步长的滑块 变量 Details 里的 Slider Range
@editable_text_box 多行文本框,可限字数 String 变量 + Multi Line 勾选
@editable_vector_slider(类型) 向量的逐分量滑块,可锁比例 / 归一化 Vector 变量的三个输入框
@editable_vector_number(类型) 向量的逐分量数值框(不带滑块) 同上,不给拖动条
@editable_container 容器的显示配置(目前限数组),如是否允许拖动排序 数组变量的 Details 选项

写法上,这些变体后面跟一个冒号,把配置项缩进写在下面——和 Verse 别处的块结构一致:

guarded_component.verse
guarded_component<public> := class<final_super>(component):

    # 滑块:0.0 ~ 10.0,每格 1.0
    @editable_slider(float):
        MinValue := option{0.0}
        MaxValue := option{10.0}
        SliderDelta := option{1.0}
    Speed<public>:float = 1.0

    # 数值框:限制在 0 ~ 10 之间
    @editable_number(int):
        MinValue := option{0}
        MaxValue := option{10}
    Lives<public>:int = 3

注意上下限用的是 option{...}——第 18 课讲过的可选值:你可以只设下限不设上限,那就只写 MinValue 一行。这比蓝图那两对必须成双填写的 Range 输入框更灵活一点。

四、分组与悬浮提示:把面板整理得像样

组件参数一多,面板就成了一锅粥。蓝图的解法是给变量填 Category 和 Tooltip;Verse 的解法一样,只是要先把文案声明成 message,再挂到属性上:

tidy_component.verse
# 面板里的分组名与提示文案,声明成可本地化的 message
MotionCategory<public><localizes>:message := "运动参数"
HeightTip<public><localizes>:message := "平台升起的高度,单位厘米"

tidy_component<public> := class<final_super>(component):

    @editable:
        ToolTip := HeightTip
        Categories := array{MotionCategory}
    Height<public>:float = 200.0

<localizes> 是本地化说明符:标了它的文案会进入翻译流程,面板上的文字将来能跟着语言走。这一点比蓝图里直接手打一串 Category 字符串要正规——蓝图的 Category 是纯英文标识,不参与本地化。

Categories 收的是一个数组,所以一个字段可以同时归入多个分组。日常够用的做法是:每个功能维度一个分组名常量,组件顶部集中声明,底下的字段各挂各的。

五、默认值与覆盖值:谁说了算

这是最容易产生误会的一节,也是最值得记牢的一节。

由此推出一条实践建议:默认值要写成「一个人不填任何东西也能看到正确效果」的值。默认 0.0 的高度、默认空字符串的名字,只会让第一次装上组件的人以为它坏了。给每个可编辑字段一个能自证的默认值,是对协作者最基本的体贴。

再补一条来自第 27 课正文的对照:蓝图变量还有 Expose on Spawn,Verse 没有同名开关。要在「生成时传参」,做法是构造实例时直接给字段赋值,比如 lift_platform_component{ Height := 300.0 }。这条路径和 Details 面板是并列的两种填值方式,不冲突。

你把组件代码里 Height 的默认值从 200.0 改成了 300.0。关卡里有一块平台,之前被策划在 Details 面板手动填成了 150.0。重新编译后,这块平台的 Height 是多少?

来源

本文整理自 Epic 官方文档:

属性变体的具体配置项会随版本增补,动手前请以当时的官方文档为准。