为什么个人项目也需要 Feature Flag
个人开发者常觉得 Feature Flag 是大团队工具。其实只要项目里同时存在正式版、Demo、内部测试、调试工具、未完成系统,就已经需要某种开关管理。否则就会出现 Demo 包含正式版章节、发行版留下调试按钮、商店截图展示了未启用功能、补丁中误开半成品系统。
Feature Flag 的目标是让功能状态可见、可控、可测试。它不是临时注释代码,也不是散落在各处的 if demo。
Flag 类型
先按用途分类:
| 类型 | 示例 | 生命周期 |
|---|---|---|
| Build | BUILD_DEMO、BUILD_REVIEW | 构建期 |
| Feature | feature_new_weapon | 实验到上线 |
| Content | content_chapter03 | 内容解锁 |
| Debug | debug_console | 内部 |
| Platform | steam_cloud_enabled | 平台能力 |
不同类型不要混用。Demo 构建开关和新武器实验开关不是一回事。分类清楚,QA 才知道该测什么。
命名规则
Flag 命名要稳定、可读:
build_demo
build_internal
feature_photo_mode
content_chapter03
debug_spawn_tools
platform_steam_cloud
不要用 test1、new_mode、temp_flag。临时开关最容易活到上线。命名里体现用途和范围,后续清理更容易。
配置来源
Flag 可以来自构建配置、配置文件或运行时参数。个人项目建议优先使用构建配置和本地配置,不要做复杂远程开关,除非项目真的需要。
| 来源 | 用途 |
|---|---|
| 构建配置 | Demo、正式版、内部版 |
| 本地配置 | 开发者调试 |
| 启动参数 | 临时诊断 |
| 平台能力 | Steam 可用状态 |
发行版不要依赖玩家可随意修改的配置来隐藏未发布内容。隐藏内容应在构建或资源层面隔离。
Demo 和正式版差异
Demo 常见差异:
- 可玩章节较少。
- 部分菜单入口隐藏。
- 结束页引导愿望单。
- 存档可能与正式版分离。
- 调试工具关闭。
这些差异应由明确配置控制,并进入 QA 表。不要在多个 UI 脚本里各写一次 if demo。最好有统一的 BuildProfile,告诉游戏当前是 Demo、Review、Internal 还是 Full。
内容锁定不是只隐藏按钮
未开放章节如果只隐藏按钮,但资源和入口仍在包里,玩家可能通过存档、控制台或文件发现。根据风险决定处理方式:
| 内容 | 处理 |
|---|---|
| 未完成关卡 | 不打进 Demo 包或入口彻底禁用 |
| 后期道具 | 从掉落和商店池移除 |
| 调试地图 | 不进发行构建 |
| 剧透文本 | 不进 Demo 本地化表 |
内容锁定要从数据、资源、UI 和存档入口一起处理。
Flag 组合爆炸
Flag 多了会产生组合爆炸。Demo + PhotoMode + NewWeapon + DebugConsole 每个组合都测不完。控制数量很重要。实验功能成熟后,要么转正删除 Flag,要么废弃删除代码。
给每个 Feature Flag 设置状态:
| 状态 | 含义 |
|---|---|
| Experimental | 内部测试 |
| Candidate | 准备上线 |
| Released | 已默认开启,应清理开关 |
| Removed | 已废弃 |
不要让实验开关永久存在。
QA 矩阵
每个构建配置都要有 QA:
| 构建 | 必测 |
|---|---|
| Demo | 章节边界、结束页、愿望单入口 |
| Full | 全章节、正式存档、成就 |
| Internal | 调试工具、测试存档 |
| Review | 审核路径、商店承诺 |
Flag 改动后,要测受影响构建。比如 content_chapter03 关闭后,Demo 是否仍能通关,正式版是否仍能进入第三章。
日志和可见性
游戏启动时写入当前构建配置和关键 Flag:
build_profile=demo flags=photo_mode:false,chapter03:false,debug_console:false
玩家反馈 Demo 里看不到某功能时,日志能判断是不是构建配置问题。内部测试也能快速确认是否拿错包。
发布前清理
发布候选前检查:
- Debug Flag 是否关闭。
- Demo Flag 是否只影响 Demo。
- 未完成 Feature 是否未进入正式构建。
- 已发布功能是否不再依赖实验开关。
- 商店截图是否对应当前 Flag 状态。
Feature Flag 的风险在于“以为关了,其实某路径还开着”。清理和 QA 都必要。
最终检查清单
- Flag 按 Build、Feature、Content、Debug、Platform 分类。
- 命名稳定清楚。
- Demo 和正式版通过统一 BuildProfile 管理。
- 内容锁定覆盖资源、数据、UI 和入口。
- Feature Flag 有生命周期。
- QA 按构建配置建立矩阵。
- 启动日志记录关键 Flag。
- 发布前清理 Debug 和废弃开关。
Feature Flag 能让个人项目更稳地并行开发 Demo、正式版和实验功能。前提是它被当成配置系统管理,而不是临时开关堆积。
Flag 和资源打包
Feature Flag 只控制逻辑还不够,资源打包也要配合。Demo 关闭第三章入口,但第三章资源仍在包里,会增加体积,也可能被玩家发现。构建配置应告诉打包流程哪些资源进入包,哪些不进入。
可以给资源加标签:
| 标签 | 进入构建 |
|---|---|
core | Demo 和正式版 |
demo_only | 只进 Demo |
full_only | 只进正式版 |
internal | 只进内部构建 |
deprecated | 不进构建 |
资源标签和功能开关一起管理,才能真正控制内容边界。
配置审计
发布前导出一份配置报告:当前 BuildProfile、启用 Flag、禁用 Flag、资源标签统计、调试入口状态。报告可以作为候选版本记录。这样几周后回看,能知道当时发出去的包到底开了什么。
如果审核反馈某功能不可见,配置报告也能帮助判断是功能没做、Flag 关闭,还是资源没打包。
删除旧 Flag 的时机
功能稳定上线后,不要让 Flag 长期存在。旧 Flag 会增加阅读成本,也会让测试矩阵变大。可以在一个版本后删除实验开关,把功能变成正常代码路径。删除时跑一次回归,确认没有配置还在引用。
清理 Flag 是工程卫生,不是可有可无的小事。
Flag 和存档兼容
如果某个功能被 Flag 控制,它产生的存档数据也要考虑关闭后的表现。比如实验武器开启时玩家获得了该武器,后续 Flag 关闭后旧存档里仍有它,游戏应该移除、隐藏、替换还是保留?不要等玩家读档崩溃后再决定。
实验功能进入公开测试前,先定义数据回退策略。内部测试可以重置存档,公开 Demo 不应轻易破坏玩家进度。
Flag 的负责人和到期时间
即使只有一个人,也建议给每个 Feature Flag 写“目的”和“预计清理时间”。例如 feature_photo_mode:用于 7 月内部测试,若 1.1 版本发布则转正或删除。没有到期时间的 Flag 会越积越多。
可以在配置文件旁放一张表,定期清理。项目越接近发售,越要减少不必要开关。
配置差异审查
Demo、Full、Internal 三个配置之间的差异要能一眼看懂。可以导出对比表:章节、调试工具、平台功能、存档路径、愿望单入口、日志级别。每次发包前看这张表,能减少“拿错配置打包”的风险。
构建配置错误通常很低级,但影响很大。流程化检查比事后排查便宜。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。