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

缩进式与大括号式:同一段 Verse 的两种排版

主课把代码块讲成了「冒号开块、缩进定归属」,那是默认写法。但 Verse 还有第二套排版:大括号加分号。两种写法编译出来一模一样,选哪种是风格问题——而风格问题在团队里会变成真问题。

一、同一段代码,两种排版

Verse 的每一个代码块都可以写成两种形态:冒号 + 换行 + 缩进,或者大括号 { }。块里的多个表达式,可以用换行分隔,也可以用分号 ; 分隔。先看默认的缩进式:

turret_device.verse(排版 A:缩进式)
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

turret_device := class(creative_device):

    var Ammo:int = 3

    Fire():void =
        if (Ammo > 0):
            set Ammo -= 1
            Print("开火,剩 {Ammo}")
        else:
            Print("空仓")

同样一段逻辑,把两个分支的身体换成大括号,并用分号把同一行里的两件事分开:

turret_device.verse(排版 B:分支用大括号)
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

turret_device := class(creative_device):

    var Ammo:int = 3

    Fire():void =
        if (Ammo > 0) { set Ammo -= 1; Print("开火,剩 {Ammo}") }
        else { Print("空仓") }

13 行变 10 行,行为完全一致。注意两处细节:第一,if 后面用了大括号就不写冒号了——冒号和大括号是同一个位置上的两选一;第二,类的定义体两边都还是冒号加缩进,官方文档里的类一律这么写,大括号的用武之地在函数体以内。

那能不能一路括到底?能,但你不会想看:

turret_device.verse(排版 C:别这么写)
    Fire():void = { if (Ammo > 0) { set Ammo -= 1; Print("开火,剩 {Ammo}") } else { Print("空仓") } }

这一行是合法的,也是不可读的。排版 C 存在的意义,只是提醒你:语言允许的写法和你该写的写法是两回事。

二、必须学会的一个:单行 if (X) { }

如果这一页你只带走一件事,就带走这个。翻开任何一份 Epic 官方示例代码,你都会撞见这样的行:

idiom.verse
        # 「做了就好,做不成也不管」:大括号故意空着
        if (set PlayerScores[Player] = 10) {}

        # 「取得到就用一下」:判断和取值一步完成
        if (First := Numbers[0]) { Print("第一个是 {First}") }

拆开看:Verse 的 if 必须带一个块,而这两种场景里,「走通之后」其实没什么可做的——第一行是往表里写值,写进去就完事;第二行是取到值就打印一句。用缩进式写第一行,你得占三行(if 一行,再缩进一行放个什么东西);用大括号,一对空的 {} 就把「成功了也不用做别的」这个意思说完了。

这个惯用法为什么重要:它是 Verse 处理「可能走不通的操作」的标准姿势(往 map 里写、按下标取数组、把 option 打开,都是这类操作)。读不懂 if (…) {},你就读不懂 Epic 的示例代码——而在 UEFN 里学任何 API,示例代码是主要教材。

顺带一提,那个空的 {} 不是什么特殊语法糖,它就是一个空的代码块,不产出任何有用的值。它和蓝图里「Branch 的 True 引脚拉出来一根线,但线上什么节点都没接」是同一件事。

三、什么时候用哪种

场景 建议排版 理由
类体、函数体 缩进式 官方文档一律这么写;类体在文档里也只有这一种形态
多行的分支 / 循环体 缩进式 竖着读,层级一眼可数(主课第三节的那个「阶梯」)
「做不成就算了」的 if (…) {} 大括号式 缩进式要占三行,大括号一行说完
「取到就用一下」的 if (X := …) { … } 大括号式 判断和使用挨在一起,读的人不用来回跳行
一行里想塞三件以上的事 两种都别用 拆成多行,或者抽一个函数出来

另外三条硬规矩,踩了会浪费你半小时:

四、团队里怎么统一

如果你的组正从蓝图迁过来,建议在第一天就定死两条:

  1. 默认缩进式。理由不是它更好看,而是官方文档、Epic 示例、绝大多数社区代码都是缩进式——新人抄得动、搜得到、问 AI 也答得对。风格跟着最大的那份语料走,永远是省力的选择。
  2. 给大括号式划一个明确的口子:只用于单行,且这一行不超过两件事。把它限定成「惯用法」而不是「另一种风格」,就不会出现同一个文件里两种排版打架的局面。

为什么值得为排版较这个真?因为这正是你换到文本代码之后拿到的那份红利。蓝图存成二进制资产,两个人改同一张图就得靠人肉沟通,diff 基本没法看;.verse 是纯文本,能进 Git、能做 code review、能让 AI 读了改。但这份红利有前提:diff 里只出现真正的改动。排版风格来回横跳的仓库,每次 diff 都混着一堆纯格式噪音,review 的人看两次就放弃了,红利立刻归零。

说白了,排版规矩不是审美洁癖,是为了让「这次到底改了什么」这个问题永远有一个五秒钟就能回答的版本。这件事在蓝图时代你想做也做不到,现在能做了,别自己浪费掉。

五、小测验

官方代码里常见的 if (set Scores[Player] = 10) {},末尾那对空大括号是干什么的?

来源

本文整理自 Epic 官方文档与官方语言手册:Verse Language Quick Reference(官方文档)↗ · block expression(官方文档)↗ · Book of Verse — Control Flow(官方语言手册)↗