Verse 的三条设计原则:It's Just Code / Just One Language / Metaverse First
Verse 后面那些让蓝图作者皱眉的「怪规矩」——默认不可变、改值必须写 set、缩进就是语法——几乎每一条都能追回三句话里的某一句。这一页把这三条设计原则讲清楚,你之后每遇到一条怪规矩,反应就能从「这什么鬼」变成「他们为什么这么选」。
一、It's Just Code:没有藏在面板里的第二套真相
在一个成熟的蓝图工程里,一个功能的真相通常分散在三个地方:事件图表里的连线、Details 面板里的几个勾选框,可能还有一张数据表。改一个行为之前,你得先想起来「这次该去哪几个地方看」。老手对此已经免疫了,但这套分散并不是免费的——它的账单在接手项目的人那里结。
Verse 的立场很硬:能用代码表达的东西,就不要放进面板。设备要暴露给关卡设计师去调的属性,写法是在字段上挂一个 @editable(第 22 课细讲)。它首先是代码里的一行,只是顺便在 Details 面板里生成一个可填的格子——面板是代码的投影,真相始终留在文件里。
这条原则带来的好处很朴素,但每一条都值钱:一个功能可以被一个文件说清楚;改动是几行 diff 而不是两张截图找不同;整段逻辑可以直接贴给同事、贴进代码审查、贴给 AI 助手。它也带来一个真实的代价——Verse 没有蓝图那种「运行时看着执行线一路亮过去」的可视化调试,你更多要靠 Print 和输出日志。这笔交易 Epic 做得很清楚:用一点直观,换「代码即全部事实」。
二、Just One Language:一门语言写到底
典型的虚幻工程有一条心照不宣的分工线:蓝图写玩法,C++ 写性能敏感或底层的部分,中间靠一层绑定把两边缝起来。于是每个人都要维护两套心智模型、两套调试手法,还要时刻记得「这个函数在哪一侧」。真正卡住很多蓝图作者的,往往就是这条线:想再往下走一层,得先学一门完全不同的语言。
Verse 的目标是把这条缝去掉:同一门语言,既要有脚本语言的书写手感,又要扛得住系统层的要求。一行 Print("hi") 就能跑,这是脚本语言那一面;强类型、编译期就拦下大量错误、把函数的副作用明写在签名里,这是系统语言那一面。
这一条能解释 Verse 给人的第一印象为什么有点矛盾:语法看着比 C++ 简洁得多,规矩却比大多数脚本语言严得多——数据默认不可变、改值必须显式写 set、一个函数会不会挂起、会不会失败、会不会改动世界状态,都要用效果说明符(第 22 课)写在签名里。它不是在为难你,它是在同时向人和编译器交代清楚同一件事。
对你的实际含义:天花板和地板在同一门语言里。你不需要再等「哪天把 C++ 学好了再去碰底层」——往深处走的时候,语法还是这一套,只是你用到了更多的部分。
三、Metaverse First:假设一万张图在同时跑
这是三条里最反直觉、也最能解释 Verse 性格的一条。想象一个永远不停机的世界:上千名互不认识的作者写的逻辑同时运行,玩家随时进随时出,内容随时更新。在这种环境里,「一段逻辑跑到一半失败了」不是罕见事故,是每天都在发生的日常。
所以 Verse 干脆把这件事写进了语言本身,主要是两件:
- ◇ 事务性:一段逻辑要么整体生效,要么像没发生过一样整体回滚,不留「金币扣了、道具没发」这种半成品状态。
- △ 结构化并发:「让好几条线同时跑」不需要你自己去开线程、自己去收尾,语言内建了
spawn/race/sync这类写法(第 24 课),而且规定了它们的生命周期归属。
还有一层是不许偷偷改状态:数据默认不可变、改值必须显式写 set、模块级的可变状态必须按玩家分账(第 8 课的拓展页讲过 weak_map)。当代码只有你一个人写时,这些规矩像是啰嗦;当代码是一万个人的代码之一时,它们是唯一能让人睡得着觉的东西。
换成蓝图比喻:蓝图默认「这张图是我的,世界归我管」;Verse 默认「这张图只是此刻同时跑着的一万张图之一」。两种假设写出来的语言,长相当然不一样。
四、用三条原则解释后面的「怪规矩」
这张表可以在往后的课里随时翻回来。每遇到一条不习惯的规定,先问它出自哪条原则。
| 你后面会遇到的规矩 | 出自哪条原则 | 为什么 |
|---|---|---|
数据默认不可变,要可变得写 var |
Metaverse First | 「谁都能随手改」是多人持久世界里一切麻烦的起点 |
改值必须写 set,单个 = 是比较 |
Metaverse First + It's Just Code | 每一次状态变更都要在代码里留下明确痕迹,不能靠一根线悄悄发生 |
| 没有大括号也没有分号,缩进即代码块 | It's Just Code | 排版与结构合二为一,读代码就是读结构 |
设备属性写 @editable,而不是面板上的勾选框 |
It's Just Code | 面板只是代码的投影,真相始终在文件里 |
| 函数要用效果说明符声明「我会做什么」 | Just One Language | 同一门语言要同时服务玩法层和系统层,契约必须写明白 |
| 失败不是异常,而是「这条路走不通」 | Metaverse First | 失败要能被整体回滚,才敢让上千段逻辑跑在同一个世界里 |
spawn / race / sync 内建在语言里 |
Metaverse First | 并发在持久在线世界里是常态,不是高级话题 |
顺带说一句:这三条原则也解释了 Epic 为什么要在 UE6 里从零基于 Verse 构建 Scene Graph。一套「entity 挂 component」的世界模型,天然要求组件之间边界清楚、状态不互相偷改、并发有规矩——这正好是 Metaverse First 那一条在框架层面的样子。语言和框架是一起长出来的,不是先有框架再挑语言。
五、小测一下
「数据默认不可变、改值必须显式写 set」最直接地服务于哪条设计原则?
来源与延伸
本文整理自 Epic 公开材料与语言设计者的公开演讲: