logic · 逻辑值
Verse 的布尔类型,只有 true 和 false 两个值。但 if 吃的不是它——条件要的是可失败表达式,logic 想进 if 得先加查询运算符:if (Flag?)。
就是蓝图里的 Boolean,只有 true 和 false。但要注意:Verse 的 if 不像 Branch 那样直接收 Boolean——它问的是「能不能走通」。想拿一个 logic 去当条件,得在后面补个问号 if (Flag?),把「真 / 假」翻译成「走得通 / 走不通」。
第 7 课 · logic 与 enum →
int / float / rational · 数值三件套
int 是 64 位有符号整数;float 是 IEEE 双精度浮点,字面量必须带小数点(写 1.0 不写 1);两者不做隐式转换,混算直接编译错误。int 除以 int 得到第三种类型 rational(精确分数),要用 Floor 或 Ceil 换回 int。
两种数:int 是整数(蓝图里的 Integer 引脚),float 是小数(Float 引脚)。写小数时必须带小数点(写 1.0,别写 1),否则会被当成整数。两者不会像蓝图那样自动帮你转换,直接混在一起算会亮红报错。还有个冷知识:整数 ÷ 整数得到的是第三种精确分数类型 rational,想变回整数得用 Floor(向下取整)或 Ceil(向上取整)。
第 5 课 · int 与 float →
string · 字符串
本质是 []char 的类型别名,字面量用双引号。花括号做插值:"Score: {Score}";想输出字面花括号要转义 \{。既然是数组,Length、索引、Slice 这套数组操作全部照用。
文字串,写在双引号里(蓝图里的 String)。想把一个变量的值嵌进文字,用花括号:"Score: {Score}"——花括号里的东西会被换成实际值(就像蓝图里把变量接进 Format Text 的占位符);真要打出花括号本身就转义写 \{。它底层其实是一串字符排成的数组,所以数组那套(取长度、按序号取字符、切片)对它照样管用。
第 6 课 · 字符串与插值 →
enum · 枚举
一组具名值:card_suit := enum{Clubs, Diamonds, Hearts, Spades},访问写 card_suit.Clubs。成员背后没有整数,不能转 int 或 string;分支匹配交给 case 表达式。
一组起好名字的选项,就是你在蓝图里右键新建的那个 Enumeration 资产,比如「梅花 / 方块 / 红桃 / 黑桃」。用「类型名.成员名」来取某一项(像从枚举下拉里选一个)。它背后没有藏整数,不能转成数字或文字;要按不同取值分头处理,交给 case(相当于蓝图里的 Switch on Enum)。
第 7 课 · logic 与 enum →
array · 数组
同类型元素的有序列表:类型 []int,字面量 array{1, 2, 3}。下标从 0 开始且是可失败表达式——越界不崩溃,只是失败;数组本身是不可变值,所谓「修改」其实是整体换新。
一串同类型的东西按顺序排好,就是蓝图里的 Array。按序号取(从 0 开始数),但这一步是「可能走不通」的——序号越界不会让游戏崩,只是这一步失败、走 else。还有个和蓝图不同的脾气:Verse 的数组是「只读值」,所谓「改数组」其实是整包换成一个新的。逐个处理用 ForEach。
第 12 课 · array 数组 →
map · 映射
键值对登记表:类型 [string]int,字面量 map{"a" => 1}。键必须是 comparable 的子类型;读和写都可失败,连 set M[K] = V 都得包进 if。
一张「键 → 值」的登记表(蓝图里的 Map):拿名字查分数、拿 ID 查血量。查和写都是「可能走不通」的——查一个不存在的键会失败,所以连往里写 set M[K] = V 都得包进一个 if。当键用的类型必须出自「能比较相等」的那一类。
第 13 课 · map 映射 →
weak_map · 弱映射
map 的特殊近亲:不能遍历、没有 Length,只能按键逐条读写。模块作用域的 var 必须是 weak_map 类型;以 player 为键、值可持久化的模块级 weak_map,正是跨会话存档的载体。
map 的一个特殊亲戚:不能整体遍历、也问不出总数,只能拿着键一条一条读写。它最重要的用途是存档——放在「类的外面」(模块层)、以玩家为键、值声明成可持久化,就成了每个玩家一份、退出重进还在的 SaveGame。
第 22 课 · 持久化数据 →
option · 选项类型
「可能有值也可能是空」的盒子:类型写 ?int,空值就是 false,装值用 option{42}(花括号,不是圆括号)。解包用后缀 ?,是可失败表达式;option{...} 本身还是个失败上下文,能把失败变成一只空盒子。
一个「可能装了东西、也可能是空」的小盒子。类型写成 ?int,空盒子就是 false,装东西用 option{42}(注意是花括号)。想把里面的东西拿出来,在后面加个问号,这一步「可能走不通」(盒子是空的就走 else)。而 option{...} 本身也是个「能容错的地方」:里面那步失败了,它不报错,只是给你一个空盒子。
第 14 课 · option 与 tuple →
tuple · 元组
定长、可混类型的一组值:类型 tuple(int, string),字面量 (1, "a")。取元素用圆括号 T(0)——位数编译期就确定,所以不可失败,但下标必须是编译期常量。函数要返回多个值,靠的就是它。
把固定几个、可以不同类型的值捆成一小包,比如「一个整数 + 一段文字」。装的时候用圆括号 (1, "a"),取第几个也用圆括号 T(0)——因为包里有几样、每样什么类型在编译时就定死了,所以取值不会失败,但序号必须是写死的常数。一个蓝图函数想一次交出好几个返回值,靠的就是它。
第 14 课 · option 与 tuple →
class · 类
引用类型的复合结构:my_class := class: 定义字段与方法,方法体内用 Self 指代当前实例。单继承一个类、可同时实现多个接口;重写成员必须标 <override>,调父类实现写 (super:)Method()。
就是蓝图类本身——把数据(字段)和行为(方法)打包成一个可以反复生成实例的东西,方法里用 Self 指「我这个实例」。只能认一个父类(像 Child Blueprint Class 那样继承),但可以同时答应多个接口;重写从父类继承来的成员必须挂 <override>(对应蓝图里那个 Override 下拉),想调父类的原版实现写 (super:)Method()。
第 16 课 · 类与继承 →
archetype · 原型
Verse 实例化对象的方式:没有 new,直接写 my_class{Field := 3},花括号里必须给所有没有默认值的字段赋值。想封装更复杂的初始化逻辑,另有 <constructor> 函数可选。
Verse 里「造一个实例」的方式:没有别处那种 new 关键字,直接写 my_class{Field := 3} 就造出一个,花括号里得把所有没给默认值的字段填上(有点像在 Details 面板里把必填项填好才能 Spawn)。想封装更复杂的初始化步骤,还能另外写一个 <constructor> 函数。
第 16 课 · 类与继承 →
struct · 结构体
值语义的纯数据聚合:赋值、传参、进容器都是整体拷贝。不能有 var 字段、体内不能定义方法(想加行为用扩展方法);小型数据组合与持久化的常客。
就是你右键新建的那个 Structure 结构体资产,一小包纯数据。它是「值」语义:赋给别人、当参数传、放进容器,都是整包复制一份(改副本不影响原件)。里面不能放会变的 var 字段、也不能写方法(想加行为用扩展方法);小数据打包和存档时的常客。
第 17 课 · struct 与 interface →
interface · 接口
只有函数签名、没有字段和实现的行为契约。类可以同时实现多个接口,每个接口方法都要用 <override> 给出实现;跨继承树的多态就靠它。
这个你已经会了——就是蓝图接口(Blueprint Interface,BPI):只列出「要有哪些函数」,不写具体实现,谁答应这个接口谁就得自己把这些函数补齐(每个都要挂 <override>)。Verse 的 interface 就是 BPI 的代码形态。一个类能同时答应好几个接口,跨不同继承树也能统一调用。
第 17 课 · struct 与 interface →
comparable · 可比较
能用 = 和 <> 判等的类型家族:int、float、logic、string、char、枚举,以及元素全部可比较的 array / map / option / tuple。map 的键必须是 comparable 的子类型,这是入场资格审查。
「能判断相等」的那一类类型:整数、小数、Boolean、文字、字符、枚举,以及里面元素都可比较的数组 / 映射 / 选项 / 元组。为什么在意它?因为 map 的键必须出自这一类——这是能不能当键的入场资格。判等用 =、判不等用 <>。
第 13 课 · map 映射 →
unique · 唯一身份
类的说明符:<unique> 类的每个实例构造时获得唯一身份,可用 = 按身份判等,因此成为 comparable——player、agent 能当 map 键正是因为它。普通类实例没有身份,压根不能比较。
一个给类挂的标签 <unique>:挂上之后,每次造出来的实例都带一张「独一无二的身份证」,可以按身份判断是不是同一个,因此也就能当 map 的键——玩家(player、agent)之所以能当键,正是这个原因。没挂这标签的普通实例没有身份证,压根不能互相比较。
第 16 课 · 类与继承 →