template/docs/intermediate/flags.md
unanmed 687e248ac1 docs(10-11): 用户修订循环 batch3(基础/其他 + 高级教程预留)
- U-01 src-tour:content 层主要在编辑器内改、对应初级教程
- U-02 data-state-overview:解释 state 静态类型按 L0-L3 逐层累加
- U-04 map-structure:按 alias/zIndex 取指定图层(非 addLayer)
- U-05 map-tiles:putMapData/getMapData 完整示例 + 高级教程预留
- U-06 flags:区分字段对象与字段值,两组接口如何选择
- U-20 events:以内置事件集已完整(发布前约 100 个)视角改写
- U-21 replay-commands:录像指令细节留高级教程
- U-22 11 篇:高级教程显式说明 + 非链接预留标记
2026-10-18 14:45:00 +08:00

4.6 KiB
Raw Blame History

Flag 变量

有些状态要跨事件、跨楼层一直保留,还要跟着存档走——比如「Boss 是否已被击败」「这道门开过没有」「某处计数到了几」。这些状态放哪?Flag 系统(state.flags)就是数据端提供的全局可存档变量:任何需要跨事件、跨楼层保留的简单状态,都可以存进 Flag,它会随存档一起保存与恢复。

字段与字段值

Flag 里的每一项都对应一个字段(IFlagCommonField)。要读懂下面的接口清单,先分清两个概念:

  • 字段是一个对象,代表「这个变量本身」,提供 get()(取值)、set(value)(设置值)、add(value)(对数字值增减)等方法;
  • 字段值就是字段里存的那个普通值(数字、字符串、布尔等)。你平时读写的,大多是字段值。

系统接口因此分成两组,看名字就能分辨:

  • **返回或操作「字段」(对象)**的:setField / getField / getOrInsert / getOrInsertComputed——它们返回字段对象本身;
  • **直接操作「字段值」**的:setFieldValue / addFieldValue / getFieldValue / getFieldValueDefaults——只关心值,不暴露字段对象。

怎么选?只读写一次值时用「值」那组更简单,不必多一步 get();要多次操作同一个字段、或要复用字段对象(例如先拿到字段、再反复增减)时,用「字段对象」那组更省事。两者可以互相转换:

// 用「字段值」的写法:一次设置、一次增减
state.flags.setFieldValue('open-count', 0);
state.flags.addFieldValue('open-count', 1);

// 用「字段对象」的写法:拿到字段后反复操作
const field = state.flags.getOrInsert('open-count', 0);
field.add(1);
const value = field.get();

其实「值」那组就是对「字段对象」那组的简写:setFieldValue(name, v) 等价于 getField(name)?.set(v),getFieldValue(name) 等价于 getField(name)?.get(),addFieldValue(name, v) 等价于 getField(name)?.add(v),getFieldValueDefaults(name, d) 等价于 getOrInsert(name, d).get()。

全部接口

IFlagSystem 提供如下接口:

接口 说明
occupied(field) 判断字段是否被占用
setField(field, value) 以指定值插入字段,返回字段对象
getField(field) 取字段对象,不存在返回 null
getOrInsert(field, defaultValue) 取字段,不存在则以默认值创建
getOrInsertComputed(field, defaultValue) 同上,但默认值由函数惰性计算
deleteField(field) 删除字段
setFieldValue(field, value) 设置字段的值
addFieldValue(field, value) 对数字字段增减
getFieldValue(field) 取字段的值,不存在返回 undefined
getFieldValueDefaults(field, defaultValue) 取字段的值,不存在则以默认值创建并返回

getOrInsertComputed 只在字段确实不存在时才执行默认值函数,适合默认值计算量较大的场景。getFieldValue 没有默认值,需要默认值时用 getFieldValueDefaults。

state.flags.setFieldValue('door-open', true);
const open = state.flags.getFieldValue('door-open');

state.flags.addFieldValue('kill-count', 1);
const count = state.flags.getFieldValueDefaults('kill-count', 0);

使用建议

Flag 会进入存档,因此不建议滥用:不再需要的变量应及时用 deleteField 删除,否则它会一直留在存档里。能用局部状态或对象自身数据表达的,就不必放进 Flag。

if (!state.flags.occupied('temp-flag')) {
    state.flags.setFieldValue('temp-flag', 1);
}

// 用完后删除,避免残留进存档
state.flags.deleteField('temp-flag');

Flag 常与游戏关键动作配合使用,例如在钩子中读写,见钩子。

示例:记录开关与计数

// 记录一个开关
state.flags.setFieldValue('boss-defeated', true);

// 记录一个计数
const times = state.flags.getOrInsert('open-count', 0);
times.add(1);

想从 state 出发找到 Flag 对象,见数据端总览。