Game

疫城札记

在绝望中,记录下你的挣扎

UnityC#生存模拟状态机多分支叙事

实机截图

状态面板
01角色状态面板 —— 生命 / 社交 / 心智 / 力量 / 智慧
随机事件
02随机事件「一位陌生的亲戚」—— 开门还是拒绝?
室内场景
03封控中的居家生活,资源与抉择
看电视
04看电视获取信息,新闻播报疫城动态
事件教程
05事件教程 —— 通过选择应对每天的事件

核心亮点

⚖️

生存与道德的权衡

每天都要面对随机事件:陌生人的求助、可疑的声响。开门还是拒绝?信任还是怀疑?每个选择都影响你与他人的命运。

🧠

耦合的状态系统

饱食度、水分、生命、心情、心智互相牵连——归零扣血、高于阈值回血。用状态机把复杂的联动规则收敛到一处。

🔀

多分支叙事

高自由度事件选择导向不同结局。用「选择序列」追踪分支,而非为每个结局单独硬编码。

核心思考

DESIGN & ENGINEERING
01

状态联动:当五个属性互相纠缠

问题

饱食度、水分、生命、心情、心智不是孤立的——饱食度/水分归零每天扣血、两者都大于 75 额外回血、生食恢复饱食度却扣心情还可能中毒。如果把这些联动规则分散写在各个资源脚本里,改动一处数值就要翻遍整个项目,极易出错。

思考

这些状态的本质是一张「有向依赖图」:某个状态变化,会触发另几个状态的连锁反应。与其把规则散落各处,不如让状态机统一持有并维护这些联动。

解决

用状态机内聚所有状态与联动规则。外部系统(事件、资源、成长)只提交「意图」,由状态机统一计算最终的状态变化。

反思

状态机把「规则」和「触发」分开了,但后来发现真正难的不是技术,而是「平衡」——比如食物中毒的概率、生食扣多少心情,这些数值直接影响玩家的情绪曲线,是需要反复测试调整的设计题。

状态机 StateMachine状态联动规则意图-结算解耦
状态联动:当五个属性互相纠缠 架构图
02

事件系统:让随机事件不侵入主流程

问题

每天都会触发随机事件,每个事件有多个选项、不同后果,还会消耗或给予资源。如果把事件逻辑直接写进主游戏循环,主流程会越来越臃肿,加一个新事件就要动核心代码。

思考

事件应该是一个「数据驱动」的独立模块:事件本身是数据,主流程只负责「把事件呈现给玩家、把玩家的选择交回给事件」去结算。

解决

事件表驱动:每个事件定义选项与后果,事件系统负责呈现与结算,主循环只在「每日结算」时向事件系统请求一个新事件。

事件系统 EventSystem数据驱动事件表选项-后果映射
03

时间驱动:每日 / 每周的稳定结算

问题

游戏有两种节奏:每日(状态增减、触发事件)和每周(电费水费、停电惩罚)。如果这些结算散落在各个脚本的 Update 里,顺序和时机都不可控。

思考

时间推进应该是「单一的时钟源」:由时间驱动层统一发出「过了一天」「过了一周」的信号,各系统监听并响应。

解决

独立的 DayTick / WeekTick 结算,统一触发状态机结算、事件触发、资源扣费,保证顺序确定、逻辑可追溯。

时间驱动 DayTick周期性结算单一时钟源
04

多结局:用选择序列追踪分支

问题

「高自由度事件选择与多分支叙事」意味着结局由玩家一路的选择累积决定。如果为每个结局单独写逻辑,分支会指数级失控。

思考

结局不是「一个开关」,而是「一路选择序列的累积结果」。记录玩家在关键事件中的选择,最后用一个判定规则导出结局即可。

解决

用选择序列记录关键抉择,结局判定表根据序列导出对应结局,避免为每个结局硬编码独立流程。

选择序列追踪结局判定表

技术细节

引擎Unity 2022 LTS
语言C#
平台PC
状态机事件系统数据驱动事件表2D 手绘美术

分层架构:表现层(手绘场景 / UI 面板 / 事件卷轴)→ 逻辑层(状态机 / 事件系统 / 叙事分支 / 资源系统)→ 时间驱动层(每日 / 每周结算)→ 数据层(事件表 / 资源数值表 / 结局判定表)。

运行时架构图

外部链接