7.7 KiB
7.7 KiB
NarrationSystem 技术参考
本文档定义并说明项目内的“旁白系统(NarrationSystem)”,以及它如何与任务系统(TaskSystem)配合,通过按钮继续/翻页在关键节点触发事件(例如添加/删除任务)。
相关脚本:
Assets/_Project/Scripts/Core/NarrationSystem/NarrationSystem.csAssets/_Project/Scripts/Core/NarrationSystem/NarrationSequence.csAssets/_Project/Scripts/Core/NarrationSystem/NarrationPage.csAssets/_Project/Scripts/UI/Narration/NarrationPanelView.cs- (可选动作)
Assets/_Project/Scripts/Core/NarrationSystem/NarrationPlayByIdAction.cs
任务系统动作脚本(用于旁白事件里绑定):
Assets/_Project/Scripts/Core/TaskSystem/Actions/AddTaskAction.csAssets/_Project/Scripts/Core/TaskSystem/Actions/RemoveTaskAction.csAssets/_Project/Scripts/Core/TaskSystem/Actions/SetTaskStatusAction.cs
1. 设计目标
- 旁白内容以“序列(Sequence)→ 多页(Page)”组织,可在 Inspector 中动态增删页数。
- 每一页都提供事件:
onEnter:进入该页时触发onContinue:玩家点击继续离开该页时触发
- 旁白系统提供统一触发入口,可被开场流程/剧情节点/触发器/互动等系统调用。
- 旁白显示时自动切换为 UI 操作模式并显示鼠标,允许玩家点击继续:
- 复用
PlayerControlLockService.Lock/Unlock(项目内既定范式)。
- 复用
2. 数据结构
2.1 NarrationDataSO(基于 ScriptableObject 的数据容器)
脚本:NarrationDataSO.cs
- 在 Project 窗口右键
Create -> Systems -> Narration -> Narration Data创建。 - 字段:
id:序列 ID(用于按 ID 播放)pages:页列表(动态长度)
2.2 NarrationPageData(单页旁白数据)
脚本:位于 NarrationDataSO.cs 内
- 字段:
text:该页显示的文本enterActionId:进入该页时触发的 Action ID(字符串)continueActionId:点击继续离开该页时触发的 Action ID(字符串)
2.3 NarrationEventListener(场景事件监听器)
脚本:NarrationEventListener.cs
- 用于将
NarrationDataSO中的字符串 Action ID 映射到场景内的UnityEvent,从而触发具体的动作(如AddTaskAction)。
3. 核心系统
3.1 NarrationSystem
脚本:NarrationSystem.cs
Inspector 槽位:
Panel View:旁白 UI 视图(NarrationPanelView)Data / Narration Database:将所有需要支持PlayById的NarrationDataSO拖入此列表。Lock Player Controls While Showing:显示时是否锁定玩家控制并显示鼠标(推荐开启)
主要接口:
PlayById(string sequenceId):按 ID 播放序列Play(NarrationDataSO sequence):直接播放序列引用Stop():停止当前旁白Continue():继续到下一页(由 UI 按钮驱动)
行为说明:
- 播放开始:显示 UI,显示鼠标(Lock),进入第 0 页并触发全局事件(带
enterActionId) - 点击继续:
- 先触发当前页全局事件(带
continueActionId) - 再进入下一页并触发新页全局事件(带
enterActionId)
- 先触发当前页全局事件(带
- 最后一页点击继续:结束播放,隐藏 UI,恢复控制(Unlock)
3.2 NarrationPanelView
脚本:NarrationPanelView.cs
Inspector 槽位:
Root:UI 根节点(用于 Show/Hide)Narration Text:TMP 文本控件Continue Button:Reach 的ButtonManager(推荐)Fallback Continue Button:如果你不用 Reach Button,可填 UnityButtonContinue Label / Finish Label:按钮文案(继续/确认)
4. 与 TaskSystem 配合(在旁白页事件里加/删任务)
因为 TaskService.AddTask(...) 这类方法需要参数,UnityEvent 直接绑不方便,推荐通过“动作脚本”承接:
AddTaskAction:- 槽位:
taskService、task、timeoutSeconds、addOrUpdate、resetStatusToTodo - 事件里绑定:
AddTaskAction.Invoke()
- 槽位:
RemoveTaskAction:- 槽位:
taskService、task - 事件里绑定:
RemoveTaskAction.Invoke()
- 槽位:
SetTaskStatusAction:- 槽位:
taskService、task、status - 事件里绑定:
SetTaskStatusAction.Invoke()
- 槽位:
典型用法:
- 进入第一页(onEnter):添加“寻找钥匙”任务
- 点击继续离开某页(onContinue):把“寻找钥匙”改为完成/移除
5. 场景搭建步骤(按顺序)
5.1 创建旁白系统根节点
- Hierarchy 新建空物体:
_NarrationSystem - 在
_NarrationSystem上 Add Component:Core.NarrationSystem.NarrationSystem - 在
_NarrationSystem下新建空物体:Sequences - 将
NarrationSystem.Sequences Root绑定到_NarrationSystem/Sequences
5.2 绑定 UI
前提:你已经制作好了旁白 UI(对话框 Text + Button)。
- 在旁白 UI 根对象上 Add Component:
UI.Narration.NarrationPanelView - 依次绑定槽位:
Root:旁白 UI 根对象(用于开关)Narration Text:你的 TMP 文本Continue Button:你的 Reach 按钮(ButtonManager)
- 把该
NarrationPanelView拖到_NarrationSystem/NarrationSystem.Panel View槽位 - 初始建议让 UI 根对象处于隐藏(SetActive=false),由系统播放时显示
5.3 制作一段开场旁白(示例)
- 在 Project 窗口右键
Create -> Systems -> Narration -> Narration Data创建一个 ScriptableObject 资产,命名为IntroNarrationData - 选中它,在 Inspector 中设置:
id:intro_awakepages添加 3 页(示例文本,可替换为你指定内容):- 第 0 页:
你醒了。头还有些疼。 - 第 1 页:
先四处看看,找到能离开这里的方法。 - 第 2 页:
如果门打不开,也许需要一把钥匙。
- 第 0 页:
- 将这个
IntroNarrationData拖入_NarrationSystem上的Narration Database列表中。
5.4 在旁白节点绑定任务事件(示例:添加“寻找钥匙”任务)
- 准备一个任务数据
TaskData:例如task_find_key - 在
IntroNarrationData的第 2 页配置:continueActionId:填入intro_awake_p2_continue
- 在场景里创建一个空物体(建议挂在
_NarrationSystem下):NarrationEventRouter - 在
NarrationEventRouter上 Add Component:Core.NarrationSystem.NarrationEventListener - 在同物体(或子物体)上 Add Component:
Core.TaskSystem.Actions.AddTaskActionTask Service:拖场景里的TaskSystem(TaskService)Task:拖task_find_keyAdd Or Update:建议勾上(防止重复触发)
- 回到
NarrationEventListener:- 添加一个 Action Mapping
actionId填入intro_awake_p2_continueonTrigger事件里拖入挂着AddTaskAction的物体,并选择GameAction -> Invoke()
5.5 将开场动画结束点接到旁白(AwakeningSequenceController)
工程已为唤醒流程增加了可绑定事件:
AwakeningSequenceController.onAwakeningFinishedinvokeFinishedWhenSkipped(继续游戏是否也触发同一事件)
按以下步骤绑定:
- 选中场景中负责开场唤醒动画的对象(挂了
AwakeningSequenceController) - 在组件
Events分组里找到On Awakening Finished - 新建一个空物体(建议挂在
_NarrationSystem下):IntroNarrationAction - 给
IntroNarrationActionAdd Component:Core.NarrationSystem.NarrationPlayByIdActionNarration System:拖_NarrationSystem (NarrationSystem)Sequence Id:填intro_awake
- 把
IntroNarrationAction.NarrationPlayByIdAction.Invoke()绑定到On Awakening Finished
运行效果:
- 唤醒动画结束 → 自动弹出旁白 UI → 鼠标可点 → 点击继续翻页 → 最后一页确认后关闭 UI 并恢复控制