16 KiB
52 · 完成度与多结局设计(Completion & Ending Design)
命名空间
BaseGames.Completion
所属文档集 ← 返回索引 · 总览
依赖BaseGames.Core.Events·BaseGames.Narrative(NarrativeStateMachine)·BaseGames.World(SaveManager)
关联 50_NarrativeDesignSystem(结局门控)· 14_ProgressionSystem · 32_AchievementSystem · 16_MapSystem
目录
- 系统总览
- 完成度计算规则
- 完成度显示界面
- NG+(新游戏+)设计
- 多结局实现流程
- 隐藏 Boss / 隐藏区域门控
- 收集品查看界面(Codex + 收藏室)
- 完成度与成就联动
- SaveData 集成
- 事件频道
- 编辑器友好设计
1. 系统总览
完成度系统为 Metroidvania 品类的核心留存引擎:玩家通关后看到"68%",会被驱动去探索剩余 32%。
完成度系统职责:
├─ CompletionTracker → 追踪所有计入完成度的元素状态
├─ CompletionCalculator → 实时计算并缓存完成度百分比
├─ CompletionUI → 暂停菜单中的完成度概览面板
├─ NgPlusManager → NG+ 流程管理(继承哪些数据、新增哪些内容)
└─ EndingDirector → 根据完成度和叙事状态导演最终结局
2. 完成度计算规则
2.1 计入完成度的元素及权重
| 类别 | 总分 | 子元素 | 每项分值 |
|---|---|---|---|
| Boss 击败 | 250 | 5 个主线 Boss × 50 | 50 / Boss |
| 房间探索 | 200 | ~100 个非 Boss 房间 × 2 | 2 / 房间 |
| 能力获取 | 100 | 10 个能力道具 × 10 | 10 / 能力 |
| 核心符文 | 80 | 16 枚核心 CharmSO × 5 | 5 / 符文 |
| 幻境碎片 | 100 | 10 个 × 10 | 10 / 碎片 |
| Lore 道具 | 150 | ~45 件 × 约 3.3 | ≈3.3 / 件 |
| NPC 最大好感度 | 80 | 4 个 NPC × 20 | 20 / NPC |
| 挑战房间 S 级 | 40 | 5 个挑战房间 × 8 | 8 / 挑战 |
| 全地图探索 | 0(隐藏加分) | 探索全部房间 | 解锁隐藏成就,不计入% |
| 合计 | 1000 分(100%) |
完成度百分比 = 当前总分 / 1000 × 100%
分值设计约束:Boss 和房间探索构成基础 45%(主线通关约达到 35~40%),收集品构成另 55%(鼓励深度探索)。
2.2 不计入完成度的内容
| 内容 | 原因 |
|---|---|
| 普通 NPC 对话 | 太多台词,不应成为义务 |
| 道具使用次数 | 不应要求玩家刷数值 |
| 死亡次数 | 不惩罚探索型玩家 |
| 钢铁之魂通关 | 计入独立成就,不影响主线 % |
2.3 CompletionTracker
namespace BaseGames.Completion
{
public class CompletionTracker : MonoBehaviour
{
[SerializeField] CompletionConfigSO _config; // SO:定义所有元素及分值
[SerializeField] WorldStateRegistry _worldState; // 叙事标志来源
[SerializeField] SaveData _saveData; // 数据来源(注入)
// 实时计算当前完成度分数(缓存,每次 SaveData 变化时更新)
public int CurrentScore { get; private set; }
public float CompletionPercent => (float)CurrentScore / _config.TotalScore * 100f;
public void RecalculateScore()
{
int score = 0;
foreach (var element in _config.Elements)
score += element.CalculateScore(_saveData, _worldState);
CurrentScore = score;
}
// 订阅所有可能影响完成度的事件频道,任意变化时重新计算
void OnEnable()
{
_onBossDefeated.OnEventRaised += _ => RecalculateScore();
_onLoreCollected.OnEventRaised += _ => RecalculateScore();
_onRoomEntered.OnEventRaised += _ => RecalculateScore();
// ... 其余事件
}
}
}
3. 完成度显示界面
3.1 暂停菜单完成度概览
暂停菜单 → "完成度" Tab 页(与任务日志并列):
┌─────────────────────────────────────────────────────────────┐
│ 游戏完成度 │
│ │
│ 总体进度: ████████████████░░░░░░░░░░░░░░░ 62% │
│ │
│ ▸ Boss 击败 ██████████████████████ 4 / 5 │
│ ▸ 房间探索 ████████████████░░░░░░ 78 / 100 │
│ ▸ 能力获取 ████████████████████░░ 9 / 10 │
│ ▸ 核心符文 ████████░░░░░░░░░░░░░░ 7 / 16 │
│ ▸ 幻境碎片 ████████████░░░░░░░░░░ 6 / 10 │
│ ▸ Lore 道具 ██████░░░░░░░░░░░░░░░░ 14 / 45 │
│ ▸ NPC 好感满级 ██████████░░░░░░░░░░░░ 2 / 4 │
│ ▸ 挑战房间 S 级 ████████████████░░░░░░ 3 / 5 │
│ │
│ [查看图鉴] [查看地图] │
└─────────────────────────────────────────────────────────────┘
- 每个类别可点击展开,显示具体哪些已完成/哪些未完成(未完成项显示"???"隐藏具体内容)
- 各类别的未完成项,仅当玩家到达该内容所在区域后才从"???"变为具体提示
- 完成度达到 80%、90%、100% 时各有一次屏幕闪光 + 成就解锁
3.2 通关结算画面
击败最终 Boss 后,在加载结局过场动画前,显示本次游玩的结算数据:
┌──────────────────────────────────────────────────────────────┐
│ 泽灵的旅程 │
│ │
│ 游玩时长 22小时 34分 │
│ 死亡次数 47 次 │
│ 总完成度 68% │
│ 结局 真实结局 · 幻境之归 │
│ │
│ [ 继续游玩(探索剩余内容) ] [ NG+ 开始 ] │
└──────────────────────────────────────────────────────────────┘
4. NG+(新游戏+)设计
4.1 NG+ 开放条件
- 任意结局通关后,在主菜单该存档槽上显示"NG+"标记
- 进入 NG+ 时,可选择继承程度(见下方)
4.2 NG+ 继承选项(玩家选择)
| 继承项 | 默认 | 选项说明 |
|---|---|---|
| 符文收集 | ✅ 继承 | 所有已获得 CharmSO |
| 能力解锁 | ✅ 继承 | 玩家已获得的运动能力 |
| 地图探索 | ✅ 继承 | 已探索的房间记录 |
| Geo 数量 | ✅ 继承 | 通关时持有的 Geo |
| 叙事进度 | ❌ 重置 | 故事节点、NPC 台词重置,但 NPC 会"认得"玩家 |
| 好感度 | 50% 继承 | 好感度减半(NPC 记得玩家但需重新深交) |
| Lore 收集 | ✅ 继承 | 图鉴内容保留 |
| Boss 进程 | ❌ 重置 | Boss 重新出现,但有 NG+ 强化版行为 |
4.3 NG+ 专属内容
每个 NG+ 层(最多 NG+3)叠加以下变化:
| NG+ 层级 | 新增内容 |
|---|---|
| NG+1 | Boss 新增隐藏攻击相位(第3阶段);敌人攻击频率 ×1.15;解锁"命魂·极限形态"符文 |
| NG+2 | 新增隐藏 Boss 入口(幻境回廊,仅 NG+2 起可进入);所有精英怪新增强化变体外观 |
| NG+3 | 解锁"逆位泽灵"皮肤;开放隐藏收藏室最终房间(含最后 3 件 Lore) |
4.4 NG+ 保护规则
- NG+ 不会覆盖原存档,系统在同一槽位的 slot 内创建
ng_plus_1子存档 - 玩家可在 NG+ 中随时回到原通关存档继续探索
4.5 NPC 对 NG+ 的特殊台词
若 SaveData.ngPlusCount >= 1,所有 NPC 初次见到玩家时会有特殊台词版本:
商人 MerchantA:"你……以前来过这里?你的眼神像是承载过整个世界的重量。"
此版本台词通过 DialogueVersion.requiredFlags = ["System_NgPlus"] 实现(由 NgPlusManager 在 NG+ 开始时设置该 WorldStateFlag)。
5. 多结局实现流程
参见 50_NarrativeDesignSystem.md §8,此处补充技术实现:
5.1 EndingDirector
namespace BaseGames.Completion
{
public class EndingDirector : MonoBehaviour
{
[SerializeField] EndingGate _endingGate;
[SerializeField] TimelineController _timelineController;
[SerializeField] AssetReference _normalEndingTimeline;
[SerializeField] AssetReference _trueEndingTimeline;
[SerializeField] AssetReference _hiddenEndingTimeline;
public async UniTask PlayEnding()
{
var endingType = _endingGate.EvaluateEnding();
// 记录到 SaveData
_saveData.LastEndingAchieved = endingType.ToString();
_saveData.CompletionPercent = _tracker.CompletionPercent;
// 根据结局类型加载对应 Timeline
var timelineRef = endingType switch
{
EndingType.Hidden => _hiddenEndingTimeline,
EndingType.True => _trueEndingTimeline,
_ => _normalEndingTimeline
};
var timeline = await Addressables.LoadAssetAsync<TimelineAsset>(timelineRef);
await _timelineController.PlayAndWaitAsync(timeline);
// 触发结算画面
UIManager.Instance.ShowEndingResult(endingType, _tracker.CompletionPercent);
}
}
}
5.2 结局差异说明
| 场景 | 普通结局 | 真结局 | 隐藏结局 |
|---|---|---|---|
| 最终 Boss 击败动画 | 相同 | 相同 | 相同 |
| 结局过场动画时长 | ~3 分钟 | ~5 分钟 | ~7 分钟 |
| 额外旁白 | 无 | 有(泽灵内心独白) | 有(含 KnightExile 对话) |
| 片尾字幕曲目 | 标准 ED 曲 | 特别 ED 曲 | 隐藏 ED 曲(特殊编曲) |
| 结算后可解锁 | NG+ | NG+ + 特殊皮肤 | NG+ + 收藏室终章 |
6. 隐藏 Boss / 隐藏区域门控
6.1 隐藏 Boss:幻境守卫(VoidSentinel)
| 属性 | 值 |
|---|---|
| 入口位置 | Ruins 区域的"幻境裂缝"(隐藏房间,需冲刺+双跳才能进入) |
| 解锁条件 | 收集 ≥ 5 个 EchoFragment + 与 ElderSage 对话 3 次以上 |
| 难度 | 显著高于同区域主线 Boss(T4 精英级) |
| 奖励 | EchoFragment #特殊(计入真结局计数)+ 专属符文 |
| 完成度 | 计入 Boss 类别(1 个额外 Boss,分值 50) |
注:隐藏 Boss 不计入 Boss 击败类别的 5/5,而是额外加分(使总分上限达到 1050,最终百分比上限 105% 而非 100%)。显示为"1 个额外 Boss 已击败"。
6.2 隐藏区域:幻境回廊
| 属性 | 值 |
|---|---|
| 开放条件 | NG+2 开始 |
| 内容 | 3 个超高难度挑战房间 + 最终 Lore 3 件 |
| 完成度贡献 | 25 分(仅 NG+2 存档计入) |
7. 收集品查看界面(Codex + 收藏室)
7.1 Codex(图鉴)
详见 50_NarrativeDesignSystem.md §6.3。图鉴从暂停菜单入口,按区域+类型分章节显示已收集 Lore。
7.2 收藏室(Gallery)
解锁条件:完成度达到 75%。
收藏室是地图中一个真实的房间(Forest 区域隐藏路径),内部墙壁随玩家收集内容逐渐出现装饰:
| 收集进度 | 收藏室变化 |
|---|---|
| Boss 全部击败 | 5 幅 Boss 肖像画挂上墙壁 |
| 幻境碎片 5/10 | 碎片拼图的一半出现在中央台座 |
| 幻境碎片 10/10 | 碎片拼图完整,台座发光,显示真结局入口提示 |
| Lore 全收集 | 书架填满,可阅读完整世界史 |
| NG+3 | 最后一个房间开启,包含开发者留言和彩蛋 |
8. 完成度与成就联动
| 完成度 | 成就名 | 平台成就 |
|---|---|---|
| 任意结局通关 | 泽灵归来 | Steam / Switch 成就 |
| 完成度 ≥ 50% | 探索者之心 | Steam 成就 |
| 完成度 ≥ 80% | 不留遗憾 | Steam 稀有成就 |
| 完成度 = 100% | 世界已属于你 | Steam 超稀有成就(徽章) |
| 真结局 | 幻境之归 | Steam 成就 |
| 隐藏结局 | 永恒见证者 | Steam 超稀有成就 |
| NG+3 通关 | 三度轮回 | Steam 稀有成就 |
成就触发通过 AchievementManager → IPlatformService.UnlockAchievement,见 32_AchievementSystem.md。
9. SaveData 集成
public class CompletionSaveData
{
// 完成度分数快照(每次存档时更新)
[JsonProperty("completionScore")]
public int CompletionScore { get; set; } = 0;
// 最后一次通关的结局类型
[JsonProperty("lastEndingAchieved")]
public string LastEndingAchieved { get; set; } // "Normal" / "True" / "Hidden"
// NG+ 层级
[JsonProperty("ngPlusCount")]
public int NgPlusCount { get; set; } = 0;
// 各类别已完成项
[JsonProperty("defeatedBosses")]
public HashSet<string> DefeatedBosses { get; set; } = new();
[JsonProperty("exploredRooms")]
public HashSet<string> ExploredRooms { get; set; } = new();
[JsonProperty("collectedAbilities")]
public HashSet<string> CollectedAbilities { get; set; } = new();
[JsonProperty("collectedCharms")]
public HashSet<string> CollectedCharms { get; set; } = new();
[JsonProperty("echoFragmentCount")]
public int EchoFragmentCount { get; set; } = 0;
[JsonProperty("collectedLoreCount")]
public int CollectedLoreCount { get; set; } = 0;
[JsonProperty("maxAffinityNPCCount")]
public int MaxAffinityNPCCount { get; set; } = 0;
[JsonProperty("challengeRoomSCount")]
public int ChallengeRoomSCount { get; set; } = 0;
}
10. 事件频道
| 频道 SO | 类型 | 触发时机 |
|---|---|---|
OnCompletionScoreChanged |
IntEventChannelSO |
完成度分数变化(传入新分数) |
OnEndingAchieved |
StringEventChannelSO |
结局过场播放(传入结局类型字符串) |
OnNgPlusStarted |
IntEventChannelSO |
NG+ 开始(传入层级) |
OnCodexComplete |
VoidEventChannelSO |
图鉴全部收集完成 |
OnHiddenAreaUnlocked |
StringEventChannelSO |
隐藏区域开放(传入 sceneAddress) |
11. 编辑器友好设计
- CompletionConfigSO Inspector:实时显示当前分值构成(饼图),方便调整权重
- CompletionTracker Inspector(Play Mode):显示各类别当前分/满分、总百分比进度条
- EndingGate Inspector:显示当前 SaveData 是否满足各结局条件(✅/❌ 清单)
- 收藏室状态 Gizmo:在 Scene View 中显示收藏室当前解锁状态颜色(绿=已解锁、灰=未解锁)
本文档版本 1.0 · 2026-04 · 关联 50_NarrativeDesignSystem / 32_AchievementSystem / 14_ProgressionSystem