Files
zeling_v2/Docs/Design/52_CompletionEndingDesign.md
2026-05-08 11:04:00 +08:00

16 KiB
Raw Permalink Blame History

52 · 完成度与多结局设计Completion & Ending Design

命名空间 BaseGames.Completion
所属文档集 ← 返回索引 · 总览
依赖 BaseGames.Core.Events · BaseGames.NarrativeNarrativeStateMachine· BaseGames.WorldSaveManager
关联 50_NarrativeDesignSystem结局门控· 14_ProgressionSystem · 32_AchievementSystem · 16_MapSystem


目录

  1. 系统总览
  2. 完成度计算规则
  3. 完成度显示界面
  4. NG+(新游戏+)设计
  5. 多结局实现流程
  6. 隐藏 Boss / 隐藏区域门控
  7. 收集品查看界面Codex + 收藏室)
  8. 完成度与成就联动
  9. SaveData 集成
  10. 事件频道
  11. 编辑器友好设计

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 次以上
难度 显著高于同区域主线 BossT4 精英级)
奖励 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 稀有成就

成就触发通过 AchievementManagerIPlatformService.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 InspectorPlay Mode显示各类别当前分/满分、总百分比进度条
  • EndingGate Inspector显示当前 SaveData 是否满足各结局条件(/ 清单)
  • 收藏室状态 Gizmo:在 Scene View 中显示收藏室当前解锁状态颜色(绿=已解锁、灰=未解锁)

本文档版本 1.0 · 2026-04 · 关联 50_NarrativeDesignSystem / 32_AchievementSystem / 14_ProgressionSystem