chore: initial commit
This commit is contained in:
534
Docs/Design/45_TutorialSystem.md
Normal file
534
Docs/Design/45_TutorialSystem.md
Normal file
@@ -0,0 +1,534 @@
|
||||
# 45 · 教程与情境提示系统
|
||||
|
||||
> **命名空间** `BaseGames.Tutorial`
|
||||
> **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md)
|
||||
> **依赖** `BaseGames.Core.Events` · `BaseGames.Player`(能力查询)· `BaseGames.UI`(提示面板)· `BaseGames.World`(SaveSystem)
|
||||
> **关联** 01_InputSystem(按键提示)· 03_PlayerSystem(能力解锁)· 14_ProgressionSystem(能力门)· 31_SaveDataSchema(首次触发记录)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [系统总览](#1-系统总览)
|
||||
2. [设计哲学:沉默式优先](#2-设计哲学沉默式优先)
|
||||
3. [ContextualHintTrigger — 情境提示触发器](#3-contextualhinttrigger--情境提示触发器)
|
||||
4. [AbilityTutorialSequence — 能力获取教学演出](#4-abilitytutorialsequence--能力获取教学演出)
|
||||
5. [InGameHintPanel — 控制器参考面板](#5-ingamehintpanel--控制器参考面板)
|
||||
6. [TooltipPopup — 单行悬浮提示](#6-tooltippopup--单行悬浮提示)
|
||||
7. [TutorialManager — 统一管理器](#7-tutorialmanager--统一管理器)
|
||||
8. [SaveData 集成](#8-savedata-集成)
|
||||
9. [多语言支持](#9-多语言支持)
|
||||
10. [编辑器友好设计](#10-编辑器友好设计)
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统总览
|
||||
|
||||
教程系统解决两个核心问题:
|
||||
1. **首次遭遇新机制** — 在玩家第一次接触特定机制时,以最小侵入方式给予提示
|
||||
2. **随时可查的操作参考** — 玩家按下专用按键可随时查看操作说明
|
||||
|
||||
```
|
||||
教程系统职责:
|
||||
├─ ContextualHintTrigger ← 区域/事件触发型提示(仅首次显示)
|
||||
├─ AbilityTutorialSequence ← 能力解锁后的专项教学演出
|
||||
├─ InGameHintPanel ← 玩家主动打开的完整操作说明面板
|
||||
├─ TooltipPopup ← 非侵入式单行浮现提示(无需关闭)
|
||||
└─ TutorialManager ← 统一状态管理、SaveData 读写
|
||||
```
|
||||
|
||||
**设计原则**:
|
||||
- 不使用强制暂停式教学("按 X 继续…"),除了第一次能力获取演出
|
||||
- 提示持续时间短(3–5 秒自动消失),不阻碍游戏进行
|
||||
- 所有提示的"已见过"状态记录在 SaveData,不重复显示
|
||||
- 提示内容随当前输入设备(键盘/手柄)自动切换图标
|
||||
|
||||
---
|
||||
|
||||
## 2. 设计哲学:沉默式优先
|
||||
|
||||
### 2.1 教学优先级
|
||||
|
||||
```
|
||||
第 1 选择(最优):通过关卡设计本身教会玩家(无任何文字/UI)
|
||||
示例:在安全环境放置单独的弱敌,玩家自然尝试攻击
|
||||
|
||||
第 2 选择:TooltipPopup 非侵入单行提示(3秒自动消失)
|
||||
示例:"↑ + 跳跃 穿越平台"(玩家首次接近单向平台时显示)
|
||||
|
||||
第 3 选择:ContextualHintTrigger(3–5秒,图文结合)
|
||||
示例:图解弹反时机(玩家首次接触弹反训练区)
|
||||
|
||||
第 4 选择(最后手段):AbilityTutorialSequence(暂停游戏,专项演出)
|
||||
仅用于:获得全新能力时,玩家必须完全理解才能继续游戏
|
||||
```
|
||||
|
||||
### 2.2 三类教学区域
|
||||
|
||||
| 类型 | 位置 | 设计方式 |
|
||||
|------|------|---------|
|
||||
| **关卡式教学** | 游戏开始的 Forest 区域 | 纯关卡设计,无 UI 提示 |
|
||||
| **机制教学区** | 每个新机制首次出现的房间 | ContextualHintTrigger + 关卡辅助 |
|
||||
| **危险预警** | 新 HazardType 首次出现 | TooltipPopup("这里危险,避免触碰")|
|
||||
|
||||
---
|
||||
|
||||
## 3. ContextualHintTrigger — 情境提示触发器
|
||||
|
||||
### 3.1 组件定义
|
||||
|
||||
```csharp
|
||||
namespace BaseGames.Tutorial
|
||||
{
|
||||
/// <summary>
|
||||
/// 区域触发型提示:玩家进入触发体区域时首次显示图文提示。
|
||||
/// 已显示过的提示不再重复(通过 TutorialManager 记录状态)。
|
||||
/// </summary>
|
||||
public class ContextualHintTrigger : MonoBehaviour
|
||||
{
|
||||
[SerializeField] ContextualHintSO _hint; // 提示内容 SO
|
||||
[SerializeField] TriggerMode _triggerMode = TriggerMode.OnPlayerEnter;
|
||||
[SerializeField] bool _showOnlyOnce = true; // false = 每次进入都显示
|
||||
|
||||
public enum TriggerMode
|
||||
{
|
||||
OnPlayerEnter, // 玩家进入触发体
|
||||
OnPlayerInRange, // 玩家持续在范围内(首次进入触发)
|
||||
OnEventRaised, // 收到指定事件频道信号
|
||||
}
|
||||
|
||||
// TriggerMode.OnEventRaised 时使用
|
||||
[SerializeField] VoidEventChannelSO _triggerChannel;
|
||||
|
||||
void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (_triggerMode != TriggerMode.OnPlayerEnter) return;
|
||||
if (!other.CompareTag("Player")) return;
|
||||
TryShowHint();
|
||||
}
|
||||
|
||||
void TryShowHint()
|
||||
{
|
||||
if (_showOnlyOnce && TutorialManager.Instance.HasSeen(_hint.hintId)) return;
|
||||
TutorialManager.Instance.ShowContextualHint(_hint);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 ContextualHintSO — 提示内容数据
|
||||
|
||||
```csharp
|
||||
[CreateAssetMenu(menuName = "Tutorial/ContextualHint")]
|
||||
public class ContextualHintSO : ScriptableObject
|
||||
{
|
||||
[Header("标识")]
|
||||
public string hintId; // 唯一 ID,如 "Hint_Parry_FirstTime"(存 SaveData)
|
||||
|
||||
[Header("显示内容")]
|
||||
public string localizationKey; // 本地化键(见 22_LocalizationSystem)
|
||||
public Sprite illustrationSprite; // 图示(可选,null = 纯文字)
|
||||
|
||||
[Header("输入图标替换")]
|
||||
public string[] actionNames; // InputActionAsset 中的 Action 名(自动替换 {Jump} 等占位符)
|
||||
|
||||
[Header("显示参数")]
|
||||
public float displayDuration = 4f; // 0 = 手动关闭
|
||||
public HintPosition position = HintPosition.BottomCenter;
|
||||
|
||||
public enum HintPosition { TopCenter, BottomCenter, TopLeft, Center }
|
||||
}
|
||||
```
|
||||
|
||||
**文本格式**(本地化字符串中):
|
||||
使用 `{ActionName}` 占位符,运行时替换为当前设备的按键图标:
|
||||
`"按下 {Parry} 在正确时机弹反敌人攻击"` → 键盘显示 `[A]`,手柄显示 `[LB]`
|
||||
|
||||
### 3.3 ContextualHint UI 样式
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════╗
|
||||
║ [插图区域 48×48px] 弹反机制 ║
|
||||
║ ║
|
||||
║ 在敌人攻击即将命中的瞬间 ║
|
||||
║ 按下 [LB] 弹反攻击 ║
|
||||
║ ║
|
||||
║ ○ 淡出消失 ║
|
||||
╚══════════════════════════════════════╝
|
||||
```
|
||||
|
||||
- 出现动画:从底部滑入 + 淡入(0.3s)
|
||||
- 消失动画:淡出(0.5s)
|
||||
- 背景:半透明黑色圆角框
|
||||
- 不阻挡玩家操作(HUD Canvas Overlay 层,不捕获输入)
|
||||
|
||||
---
|
||||
|
||||
## 4. AbilityTutorialSequence — 能力获取教学演出
|
||||
|
||||
### 4.1 触发时机
|
||||
|
||||
每当玩家通过 `AbilityUnlock` 获取新能力时,自动播放专项教学演出:
|
||||
|
||||
```
|
||||
AbilityUnlock.OnTriggerEnter2D
|
||||
→ PlayerStats.UnlockAbility(abilityType)
|
||||
→ SaveManager.MarkCollected(unlockId)
|
||||
→ 播放 acquisitionFeedback
|
||||
→ TutorialManager.PlayAbilityTutorial(abilityType) ← 新增
|
||||
```
|
||||
|
||||
### 4.2 教学演出流程
|
||||
|
||||
```
|
||||
AbilityTutorialSequence 播放流程:
|
||||
|
||||
1. 暂停游戏(Time.timeScale = 0,但 UIAnimator 不受影响)
|
||||
2. 全屏黑色遮罩淡入(0.4s)
|
||||
3. 画面中央显示能力图标 + 动画(Scale 放大 + 粒子效果,1.2s)
|
||||
4. 显示能力名称(大标题,从下向上飞入,0.6s)
|
||||
5. 显示能力说明(简短一行,0.4s 延迟)
|
||||
6. 显示操作说明(包含输入图标,0.4s 延迟)
|
||||
7. 显示"按任意键继续"提示(0.6s 延迟后出现)
|
||||
8. 玩家输入 → 遮罩淡出 → 恢复 Time.timeScale
|
||||
```
|
||||
|
||||
### 4.3 AbilityTutorialSO — 能力教学配置
|
||||
|
||||
```csharp
|
||||
[CreateAssetMenu(menuName = "Tutorial/AbilityTutorial")]
|
||||
public class AbilityTutorialSO : ScriptableObject
|
||||
{
|
||||
public AbilityType abilityType; // 对应能力类型
|
||||
|
||||
[Header("演出资产")]
|
||||
public Sprite abilityIcon; // 能力大图标(128×128px)
|
||||
public string abilityNameLocKey; // 本地化键:"ABILITY_DOUBLE_JUMP"
|
||||
public string descriptionLocKey; // 简短说明(1–2 行)
|
||||
public string[] usageInstructionLocKeys; // 操作说明(1–3 条,含 {ActionName} 占位)
|
||||
public MMF_Player acquisitionFeedback; // 播放音效和粒子的 Feel Player
|
||||
}
|
||||
```
|
||||
|
||||
**资产存放**:`Assets/ScriptableObjects/Tutorial/AbilityTutorials/`
|
||||
|
||||
### 4.4 能力教学 SO 对照表
|
||||
|
||||
| 能力 | abilityType | 说明示例 |
|
||||
|------|------------|---------|
|
||||
| 双跳 | `DoubleJump` | "在空中再次跳跃,到达更高的地方" |
|
||||
| 冲刺 | `AerialDash` | "快速冲向一个方向,躲避攻击或穿越间隙" |
|
||||
| WallGrab | `WallGrab` | "按住方向键贴向墙壁,抓住墙面停下" |
|
||||
| 游泳 | `Swim` | "进入液体后自动激活,按跳跃键上浮" |
|
||||
| 天魂形态 | `SkyForm` | "切换到天魂形态,解锁天魂技能" |
|
||||
| 地魂形态 | `EarthForm` | "切换到地魂形态,解锁地魂技能" |
|
||||
| 命魂形态 | `DeathForm` | "切换到命魂形态,解锁命魂技能" |
|
||||
|
||||
---
|
||||
|
||||
## 5. InGameHintPanel — 控制器参考面板
|
||||
|
||||
### 5.1 功能概述
|
||||
|
||||
玩家随时按下 `Help` 按键(默认 `F1` / `Select` 按钮)打开完整操作说明面板,**不暂停游戏**:
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════╗
|
||||
║ 🎮 操作说明 [ESC关闭] ║
|
||||
║────────────────────────────────────────────────────║
|
||||
║ 基础操作 战斗 ║
|
||||
║ ←/→ 移动 [Z/LB] 攻击 ║
|
||||
║ [X/A] 跳跃 [X/A] 弹反 ║
|
||||
║ 双击 [X/A] 双跳 ★ ←↓→ + [A] 方向攻击 ║
|
||||
║ [C/RT] 冲刺 ★ ║
|
||||
║ 形态切换 ║
|
||||
║ 进阶移动 [1/D-↑] 天魂形态 ★ ║
|
||||
║ 贴墙+方向 WallGrab ★ [2/D-↓] 地魂形态 ★ ║
|
||||
║ WallGrab中 [X/A] 墙跳 [3/D-→] 命魂形态 ★ ║
|
||||
║ ║
|
||||
║ ★ = 需解锁后可用 [翻页 ▶] ║
|
||||
╚════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
**灰显规则**:已解锁的能力正常显示;未解锁的能力文字灰色+问号替代图标(保留神秘感但告知存在)。
|
||||
|
||||
### 5.2 InGameHintPanel 组件
|
||||
|
||||
```csharp
|
||||
public class InGameHintPanel : MonoBehaviour
|
||||
{
|
||||
// 由 CanvasGroup 控制显示/隐藏,不暂停 Time.timeScale
|
||||
[SerializeField] CanvasGroup _panelGroup;
|
||||
[SerializeField] InputReaderSO _input;
|
||||
[SerializeField] PlayerStats _playerStats; // 查询已解锁能力
|
||||
|
||||
void OnEnable() => _input.HelpEvent += Toggle;
|
||||
void OnDisable() => _input.HelpEvent -= Toggle;
|
||||
|
||||
void Toggle()
|
||||
{
|
||||
bool show = _panelGroup.alpha < 0.5f;
|
||||
_panelGroup.DOFade(show ? 1f : 0f, 0.2f).SetAutoKill(true);
|
||||
_panelGroup.interactable = _panelGroup.blocksRaycasts = show;
|
||||
RefreshAbilityHighlights();
|
||||
}
|
||||
|
||||
void RefreshAbilityHighlights()
|
||||
{
|
||||
// 根据 _playerStats.HasAbility() 动态更新图标颜色/灰显
|
||||
foreach (var entry in _abilityEntries)
|
||||
entry.SetUnlocked(_playerStats.HasAbility(entry.abilityType));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. TooltipPopup — 单行悬浮提示
|
||||
|
||||
### 6.1 用途
|
||||
|
||||
最轻量的提示方式,不含图片,不阻塞操作:
|
||||
|
||||
```
|
||||
示例显示效果(屏幕底部):
|
||||
┌─────────────────────────────────────┐
|
||||
│ ↓ + [X] 可以穿过此平台 │
|
||||
└─────────────────────────────────────┘
|
||||
(3秒后自动消失)
|
||||
```
|
||||
|
||||
### 6.2 使用场景
|
||||
|
||||
| 触发时机 | 提示内容 |
|
||||
|---------|---------|
|
||||
| 玩家首次站上单向平台 | "↓ + {Jump} 可以穿过此平台" |
|
||||
| 玩家首次接近 SavePoint | "按 {Interact} 存档并恢复 HP" |
|
||||
| 玩家首次进入暗区 | "此区域能见度降低" |
|
||||
| 玩家首次遇到可弹反弹射物 | "可弹反的弹射物会发出白光" |
|
||||
| Geo 首次掉落在死亡处 | "取回死亡时掉落的 Geo" |
|
||||
|
||||
### 6.3 代码接口
|
||||
|
||||
```csharp
|
||||
// 任意系统调用(通过事件频道,零耦合):
|
||||
_tooltipChannel.Raise(new TooltipData
|
||||
{
|
||||
localizationKey = "HINT_ONEWAY_PLATFORM",
|
||||
duration = 3f,
|
||||
showOnlyOnce = true,
|
||||
hintId = "OWPlatform_FirstTime"
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. TutorialManager — 统一管理器
|
||||
|
||||
```csharp
|
||||
namespace BaseGames.Tutorial
|
||||
{
|
||||
/// <summary>
|
||||
/// 单例管理器:记录已展示提示的状态,派发提示请求到 UI 层。
|
||||
/// 位于 Persistent 场景,通过事件频道通信,不持有具体 UI 引用。
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-50)]
|
||||
public class TutorialManager : MonoBehaviour
|
||||
{
|
||||
public static TutorialManager Instance { get; private set; }
|
||||
|
||||
[SerializeField] TooltipEventChannelSO _tooltipChannel; // 订阅:发送单行提示
|
||||
[SerializeField] HintEventChannelSO _hintChannel; // 订阅:发送图文提示
|
||||
[SerializeField] AbilityTutorialSO[] _abilityTutorials;// 所有能力教学 SO 数组
|
||||
|
||||
HashSet<string> _seenHints = new(); // 运行时缓存,启动时从 SaveData 加载
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
LoadSeenHints();
|
||||
}
|
||||
|
||||
public bool HasSeen(string hintId) => _seenHints.Contains(hintId);
|
||||
|
||||
public void ShowContextualHint(ContextualHintSO hint)
|
||||
{
|
||||
_seenHints.Add(hint.hintId);
|
||||
SaveSeenHints();
|
||||
_hintChannel.Raise(hint);
|
||||
}
|
||||
|
||||
public void PlayAbilityTutorial(AbilityType type)
|
||||
{
|
||||
var tutorial = System.Array.Find(_abilityTutorials, t => t.abilityType == type);
|
||||
if (tutorial == null) return;
|
||||
StartCoroutine(PlayTutorialSequence(tutorial));
|
||||
}
|
||||
|
||||
IEnumerator PlayTutorialSequence(AbilityTutorialSO tutorial)
|
||||
{
|
||||
Time.timeScale = 0f;
|
||||
_hintChannel.Raise(tutorial); // 专用全屏演出
|
||||
// 等待玩家任意键确认(UnscaledTime)
|
||||
yield return new WaitUntil(() => Input.anyKeyDown);
|
||||
Time.timeScale = 1f;
|
||||
}
|
||||
|
||||
void LoadSeenHints()
|
||||
{
|
||||
var data = SaveManager.Instance?.CurrentSave?.tutorial?.seenHints;
|
||||
if (data != null) _seenHints = new HashSet<string>(data);
|
||||
}
|
||||
|
||||
void SaveSeenHints()
|
||||
{
|
||||
if (SaveManager.Instance?.CurrentSave?.tutorial == null) return;
|
||||
SaveManager.Instance.CurrentSave.tutorial.seenHints = new List<string>(_seenHints);
|
||||
SaveManager.Instance.MarkDirty(); // 不立刻写盘,等下次存档点触发
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. SaveData 集成
|
||||
|
||||
### 8.1 SaveData 字段扩展
|
||||
|
||||
在 `31_SaveDataSchema_Unified.md` 的 C# 结构中添加 `tutorial` 节点:
|
||||
|
||||
```csharp
|
||||
// SaveData.cs 中新增字段
|
||||
public class TutorialSaveData
|
||||
{
|
||||
public List<string> seenHints = new(); // 已展示过的提示 ID 列表
|
||||
public List<string> completedTutorials = new(); // 已完成的能力教学 ID 列表
|
||||
}
|
||||
|
||||
// 主 SaveData 结构
|
||||
public class SaveData
|
||||
{
|
||||
// ...(原有字段)
|
||||
public TutorialSaveData tutorial = new();
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 JSON Schema 扩展
|
||||
|
||||
```json
|
||||
{
|
||||
"tutorial": {
|
||||
"seenHints": ["OWPlatform_FirstTime", "Parry_FirstTime", "SavePoint_FirstTime"],
|
||||
"completedTutorials": ["DoubleJump", "AerialDash"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 新游戏 / 存档重置行为
|
||||
|
||||
- 新游戏:`tutorial` 节点为空,所有提示将依序展示
|
||||
- 读取存档:从 `seenHints` 列表恢复已见过的提示,不重复展示
|
||||
- 存档删除:整个 `tutorial` 节点重置为空
|
||||
|
||||
---
|
||||
|
||||
## 9. 多语言支持
|
||||
|
||||
所有提示文本通过 `localizationKey` 引用 `22_LocalizationSystem` 的字符串表,**不在 SO 中硬编码文字**:
|
||||
|
||||
```csharp
|
||||
// 使用方式示例
|
||||
string text = LanguageManagerSO.Instance.GetString(hint.localizationKey);
|
||||
|
||||
// 输入图标替换(替换 {ActionName} 占位符)
|
||||
text = InputIconReplacer.Replace(text, hint.actionNames);
|
||||
// 输出示例(手柄):"按下 [图标:LB] 在弹反窗口内反击"
|
||||
```
|
||||
|
||||
**本地化键命名规范**:`HINT_{机制简称}_{情境}_{语言变体}`
|
||||
|
||||
示例:
|
||||
- `HINT_ONEWAY_FIRST` → "↓ + {Jump} 可以穿过此平台"
|
||||
- `HINT_PARRY_TIMING` → "在攻击命中瞬间按 {Parry}"
|
||||
- `HINT_SHADE_COLLECT` → "拾取遗骸可取回死亡时掉落的 Geo"
|
||||
|
||||
---
|
||||
|
||||
## 10. 编辑器友好设计
|
||||
|
||||
### 10.1 TutorialDebugOverlay
|
||||
|
||||
运行时叠加层(仅 `UNITY_EDITOR || DEVELOPMENT_BUILD`):
|
||||
|
||||
```
|
||||
TutorialDebugOverlay(按 F2 切换显示):
|
||||
┌─ Tutorial Debug ─────────────────────────────────┐
|
||||
│ 已见提示数: 12 / 28 │
|
||||
│ 当前队列: [空] │
|
||||
│ ─────────────────────────────────────────────── │
|
||||
│ [重置所有提示] [标记所有已见] [导出未见列表] │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 10.2 ContextualHintTrigger 自定义 Inspector
|
||||
|
||||
```
|
||||
ContextualHintTrigger Inspector:
|
||||
┌─ Hint SO ──────────────────────────────────────┐
|
||||
│ Hint: [OWPlatform_Hint] │
|
||||
│ hintId: "OWPlatform_FirstTime" │
|
||||
│ Duration: 3.0s │
|
||||
│ ───────────────────────────────────────────── │
|
||||
│ [▶ 预览提示效果(Editor Play Mode 中)] │
|
||||
│ [已见状态: 未见 ▶ 点击模拟"已见"] │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 10.3 HintTrigger Gizmos
|
||||
|
||||
- `ContextualHintTrigger` 的触发区域在 Scene 视图显示为**浅蓝色边框虚线框**
|
||||
- 框内显示 hintId 字符串(白色小字)
|
||||
- 鼠标悬停时显示提示文本预览(Tool Tip)
|
||||
|
||||
---
|
||||
|
||||
## 附录:推荐提示 ID 规范
|
||||
|
||||
所有 hintId 字符串集中在静态类中定义(类似 `GameFlags`):
|
||||
|
||||
```csharp
|
||||
// Assets/Scripts/Tutorial/TutorialHintIds.cs
|
||||
public static class TutorialHintIds
|
||||
{
|
||||
// 移动
|
||||
public const string OWPlatformDropDown = "OWPlatform_DropDown";
|
||||
public const string WallGrabIntro = "WallGrab_Intro";
|
||||
public const string DoubleJumpIntro = "DoubleJump_Intro";
|
||||
public const string DashIntro = "Dash_Intro";
|
||||
|
||||
// 战斗
|
||||
public const string ParryTimingIntro = "Parry_Timing_Intro";
|
||||
public const string ParryableProjectile = "Parry_Projectile";
|
||||
public const string BossPhaseChange = "Boss_PhaseChange";
|
||||
|
||||
// 世界
|
||||
public const string SavePointFirst = "SavePoint_First";
|
||||
public const string ShadeCollect = "Shade_Collect";
|
||||
public const string BenchFastTravel = "Bench_FastTravel";
|
||||
public const string ShopFirst = "Shop_First";
|
||||
|
||||
// 形态系统
|
||||
public const string FormSwitchIntro = "Form_Switch_Intro";
|
||||
public const string SkyFormSkillIntro = "Form_Sky_Skill";
|
||||
|
||||
// 危险
|
||||
public const string PoisonZoneFirst = "Hazard_Poison_First";
|
||||
public const string LavaZoneFirst = "Hazard_Lava_First";
|
||||
public const string InstantKillFirst = "Hazard_InstantKill_First";
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*文档版本 1.0 · 2026*
|
||||
Reference in New Issue
Block a user