拔高 · EXTRA
Verse 演算:给函数式逻辑编程一个数学核心
Simon Peyton Jones 与 Tim Sweeney 等人在 ICFP 2023 发表的论文,为 Verse 提供了 lambda 演算级别的形式化内核——「失败取代布尔值」这些怪设计的理论根基都在这里。
进入拓展 →这一课不背语法、不装环境,只做三件事:搞清楚 Verse 是什么、它为什么值得你花时间,然后亲眼看着你的第一段 Verse 代码一行行跑起来。放轻松,当成开新号玩就行。
Verse 是 Epic Games 打造的编程语言,也是 UE6 的官方脚本语言。如果说引擎编辑器是一张巨大的乐高工作台,那 Verse 就是给积木注入灵魂的咒语——按钮为什么会开门、倒计时为什么会响、Boss 为什么会在你踩到机关时出现,背后全是 Verse 在发号施令。
它不是一门实验室里的新语言。Verse 于 2023 年 3 月随 UEFN(UE6 中面向 Fortnite 的创作环境)上线,此后一直在数以万计的 Fortnite 岛屿上担任唯一的游戏逻辑脚本语言——等于在数亿玩家面前公测了好几年才走到你面前。如今 Epic 把 UE5 与 UEFN 两条产品线汇成了 UE6,gameplay 编程的正统入口就是 Verse:官方的说法是它「把 C++ 事务化」,目标是支撑数千名贡献者协作的大规模持久在线体验。Actor 与蓝图在 UE6 的早期版本里仍然保留,官方也承诺了迁移工具,但方向已经写在路标上了。
再说说它不寻常的血统:Verse 是一门函数式逻辑语言(functional logic language)。它由 Epic 创始人 Tim Sweeney 亲自主导构思——他自述这门语言在脑子里酝酿了大约十年;2021 年 12 月,Haskell 之父级人物 Simon Peyton Jones 加入 Epic 出任 Engineering Fellow 参与设计,同行的还有 Lennart Augustsson 等一票函数式编程界的传奇人物。一门为游戏而生的工业语言,却有着学院派的顶配血统——这在编程语言史上都算稀罕事,也解释了后面你会遇到的很多「怪而妙」的设计。
在动手之前,先回答那个最实际的问题:我为什么要把时间投给 Verse?
下面是一个完整、可以直接编译运行的 Verse 设备,正是官方 Verse Device 模板生成的经典 Hello 程序。它的全部使命:在游戏体验开始时,向世界喊出「Hello, world!」,顺便现场算一道数学题。别急着理解每个字,先点「运行下一步」,像看回放一样,看代码是怎么一行行执行的。
读图翻译(蓝图视角):这段代码要是拿蓝图搭,就是一个以 creative_device 为父类的蓝图类,里面放一个 Event BeginPlay 事件;从 BeginPlay 拉出执行线,先接一个 Print String 节点(内容是 Hello, world!),再接第二个 Print String(内容里用 {2 + 2} 现场算出 4)。下面的步进器会把这几个「节点」一行行点亮给你看。
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# 我的第一个 Verse 设备
hello_world_device := class(creative_device):
OnBegin<override>()<suspends>:void =
Print("Hello, world!")
Print("2 + 2 = {2 + 2}")
点「运行下一步」,看代码怎么一行行执行。
看到了吗?短短几行,一个「会说话的设备」就完工了。现在把它拆开,一块积木一块积木地看:
using { /Fortnite.com/Devices } —— 借工具箱。Verse 的能力分装在不同模块里,模块路径长得像网址(/Fortnite.com、/Verse.org、/UnrealEngine.com),using 就是开工前把需要的工具箱搬到手边。(有趣的小知识:Print 本身来自 /Verse.org/Verse 模块,不用显式引入就能用;模板里的第三行 Diagnostics 引入的是其他诊断工具。)hello_world_device := class(creative_device): —— 定义一块新积木。:= 读作「定义为」:hello_world_device 被定义为一个继承 creative_device 的类。注意这个带冒号的 :=,它和单独的 = 完全是两回事,常见坑一节见。:= 读作「定义为」——相当于在内容浏览器里右键新建一个蓝图类,并把 creative_device 选成它的父类(就像做一个 Child Blueprint Class)。留意它带着冒号:和单独的 = 是两码事,后者是「比较相不相等」而不是「定义」,常见坑一节见。OnBegin<override>()<suspends>:void = —— 开场哨。游戏体验一开始它就被自动调用,想让什么事在开局发生,就写在这里。尖括号里的 <override> 和 <suspends> 现在不用深究,记住「OnBegin 固定这么写」,下一课我们专门拆它。Print("...") —— 回声法术。把文字打到屏幕左上角的调试文字区和 UEFN 的输出日志(Output Log),是你以后天天要用的「确认代码跑没跑到」神器。# 开头的那行 —— 注释,写给人看的便签,机器直接跳过。你已经能逐行读懂一段真正的 Verse 代码了——这可是很多人卡在「第一页」的地方。
你可能注意到一个细节:这段代码里没有任何大括号来圈定「哪些代码属于谁」(using 后面那对花括号是模块路径的写法,不是代码块),行尾也没有分号。这段代码里没有一个用来圈定「哪些代码属于谁」的括号,行尾也没有任何收尾符号——这些符号本来就不是给你连蓝图时用的,不用找。(using 后面那对花括号是模块路径的写法,不是代码块。)Verse 靠的是缩进——每往右缩进 4 个空格,就表示「我隶属于上一层」。就像列队:站在队长身后同一列的,就是他的队员。
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
indent_demo := class(creative_device):
OnBegin<override>()<suspends>:void =
Print("我缩进在 OnBegin 之下,所以我属于 OnBegin")
Print("我和上一行对齐,我们是同一小队")
读一下这段队形:OnBegin 缩进 4 格,所以它属于 indent_demo 这个类;两句 Print 再缩进 4 格,所以它们都属于 OnBegin,开局时会一句接一句执行。队形一旦站错——比如少打一个空格、或者混进一个 Tab——编译器就会报错,因为它读不懂这行代码「归谁管」。
三条保命贴士:① 缩进永远用 4 个空格,别用 Tab 和空格混搭;② 同一层级的代码必须严格对齐;③ 在 VS Code(官方指定的 Verse 编辑器,随 UEFN 一起安装 Verse 扩展)里按 Tab 会自动转成空格,放心敲。缩进不是装饰,它就是语法本身。
如果你碰过 C++、JavaScript 或 Python,有几个条件反射会在第一周反复坑你;如果你是纯新手,恭喜,这些坑对你反而不存在。提前把它们钉在墙上:
你是从蓝图连线过来的,严格说没有「别的文本语言」落下的坏习惯——不过下面这几条正好是蓝图的直觉和 Verse 不一样的地方,提前看一眼,能少踩几个坑:
:= 才是「定义为」,单独的 = 是一次可失败的相等比较。想赋值却写了 X = 5,轻则编译错误,重则语义完全不是你想的那样。这是 Verse 和几乎所有主流语言最大的分歧点,第 4 课我们专门算这笔账。set X = 5(就相当于那个 Set 节点);而单独的 = 是一次可失败的相等比较,不是赋值。把两者搞混轻则编译报错,重则逻辑完全跑偏,第 4 课专门算这笔账。Print 的输出只在启动会话(playtest session)后才会出现。光点 Build 然后盯着日志发呆,是每个新人都干过的事。print("hi") 无法通过编译,必须是 Print。官方命名约定也值得现在就记住:类型用小写 snake_case(如 creative_device),函数和标识符用 PascalCase(如 Print、OnBegin)。print("hi") 编译不过,必须首字母大写的 Print。命名习惯记两条就够:设备和类型用全小写加下划线(像 creative_device),函数和变量名每个词首字母大写(像 Print、OnBegin)——这跟你在蓝图里给变量、函数起名的讲究其实一个道理。第一课的 Boss 战来了(放心,是史莱姆级别的)。答对拿星星 ★,答错可以无限重试,不掉血。
Verse 靠什么来划分代码块(表示「这几行代码属于谁」)?
在 Verse 里想表达「把 hello_world_device 定义为一个类」,应该用哪个符号?
代码 Build 成功了,但日志里一行输出都没有。最可能的原因是?
拔高 · EXTRA
Simon Peyton Jones 与 Tim Sweeney 等人在 ICFP 2023 发表的论文,为 Verse 提供了 lambda 演算级别的形式化内核——「失败取代布尔值」这些怪设计的理论根基都在这里。
进入拓展 →拓展 · EXTRA
官方新闻《The road to UE6》怎么解释 UE5 与 UEFN 的合并、「把 C++ 事务化」到底什么意思,以及蓝图和 Actor 的去向——一页回答「学 Verse 是不是白学」。
进入拓展 →拓展 · EXTRA
一份带年表的番外:Tim Sweeney 酝酿十年的语言草稿,如何等来 Simon Peyton Jones 和 Haskell 首个编译器的作者,最终落地成 UE6 的官方脚本语言。
进入拓展 →