13 KiB
Persistent 场景配置手册
文件位置:
Docs/Guides/03_Persistent_Scene_Setup_Guide.md
版本:1.0 · 适用项目:zeling_v2
目录
1. 架构概览
Persistent 场景在整个游戏生命周期内常驻内存,承载所有跨场景的全局系统。 游戏场景(关卡、主菜单等)以 Additive 方式叠加在它之上。
[Persistent Scene]
├── [SERVICES] ← 纯逻辑:SceneService, GameManager, AudioManager ...
└── [UI]
├── UIRoot ← UIManager(面板栈管理)
│ ├── HUD Canvas / HUDRoot
│ ├── DeathScreen Canvas / DeathScreenRoot
│ ├── PauseMenuRoot
│ ├── SettingsRoot
│ ├── MapRoot
│ └── ShopRoot
├── Canvas_Splash ← SplashScreenController(启动演出)
├── Canvas_Loading ← LoadingScreenManager(加载遮罩)
└── SYS_SceneFade ← SceneFadeController(场景切换黑幕)
├── FeedbackFadeOut ← SceneFeedback + MMF_Player ★需手动配置
└── FeedbackFadeIn ← SceneFeedback + MMF_Player ★需手动配置
调用链(场景切换):
RoomTransition / DoorTransition(游戏场景)
→ ServiceLocator<ISceneService>.RequestTransition(request)
→ SceneService.LoadSceneCoroutine()
→ EVT_FadeOutRequest.Raise()
→ 等待 _sceneFadeDuration(默认 0.4 s)
→ 加载目标场景
→ EVT_FadeInRequest.Raise()
EVT_FadeOutRequest / EVT_FadeInRequest
→ SceneFadeController(Persistent 场景)
→ SceneFeedback.Play()
→ MMF_Player.PlayFeedbacks() ← 实际视觉效果在此配置
2. 快速开始:脚手架工具
在 空的 Persistent 场景 中执行:
菜单栏 → BaseGames → Scene → Setup → Scaffold Persistent Scene
脚手架完成后会在编辑器底部输出一份报告,列出所有已自动绑定的内容及仍需手动处理的项目。 请务必阅读该报告再继续。
前提条件
运行脚手架前,先执行BaseGames → Scene → Setup → Create All Event Channel Assets
确保所有事件频道 SO 资产已生成,脚手架才能自动绑定引用。
3. 自动生成内容速查
脚手架会自动完成以下所有节点的创建与字段绑定:
| 节点 / 组件 | 自动创建子节点 | 自动绑定字段 |
|---|---|---|
UIRoot / UIManager |
HUD Canvas、DeathScreen Canvas、PauseMenuRoot、SettingsRoot、MapRoot、ShopRoot | _hudRoot、_deathScreenRoot、_addressablePanelParent、_panels[4]、全部事件频道 |
DeathScreenRoot / DeathScreenController |
RespawnButton(Button)、DeathMessage(TextMeshProUGUI) |
_btnRespawn、_deathMessage、_onDeathScreenConfirmed |
PauseMenuRoot / PauseMenuController |
Btn_Resume、Btn_Settings、Btn_MainMenu、Btn_Quit(各带 Button) |
4 个按钮引用、_onResumeRequested、_onSceneLoadRequest |
Canvas_Splash / SplashScreenController |
StudioLogo(CanvasGroup)、GameTitle(CanvasGroup) |
_splashRoot、_studioLogoGroup、_gameTitleGroup、事件频道 |
Canvas_Loading / LoadingScreenManager |
LoadingRoot、ProgressBarFill(Image.Filled)、TipText(TextMeshProUGUI) |
_loadingRoot、_progressFill、_tipText、事件频道 |
SYS_SceneFade / SceneFadeController |
FeedbackFadeOut(MMF_Player + SceneFeedback)、FeedbackFadeIn(MMF_Player + SceneFeedback) |
_fadeOut、_fadeIn、_onFadeOutRequest、_onFadeInRequest |
4. 手动配置项详解
4.1 SceneFade:配置 MMF_Player 淡入淡出效果
这是唯一的核心视觉必配项,脚手架已创建好节点和组件,但 MMF_Player 内部的具体效果需要手动添加。
节点路径:
[UI] → SYS_SceneFade → FeedbackFadeOut (淡出:画面变黑)
[UI] → SYS_SceneFade → FeedbackFadeIn (淡入:画面显现)
配置步骤(FeedbackFadeOut):
-
选中
FeedbackFadeOutGameObject -
在 Inspector 中找到
MMF Player组件,点击+添加 Feedback -
选择
UI > Canvas Group Alpha(推荐)或Rendering > PostProcessing -
配置参数:
- 目标 CanvasGroup:创建一个全屏黑色 Image 挂在
SYS_SceneFade下,添加CanvasGroup,将其拖入 - Alpha From:
0→ Alpha To:1(淡出 = 变黑) - Duration:
0.35 s(需 ≤SceneService._sceneFadeDuration,默认0.4 s)
- 目标 CanvasGroup:创建一个全屏黑色 Image 挂在
-
配置
FeedbackFadeIn(镜像操作):- Alpha From:
1→ Alpha To:0(淡入 = 显现) - Duration 同上
- Alpha From:
重要约束
MMF_Player 的总时长(Duration)必须 ≤SceneService._sceneFadeDuration(默认 0.4 s),
否则淡出动画尚未播完,场景已开始加载,视觉上会有闪烁。
如需更长的过渡,在SERVICES → SceneServiceInspector 中同步调大_sceneFadeDuration。
推荐全屏遮罩层级结构:
SYS_SceneFade
├── ScreenOverlay ← Image(全屏黑色)+ CanvasGroup(alpha 0)
│ 需在此 Canvas 上设置 Sort Order 高于所有其他 UI Canvas
├── FeedbackFadeOut ← SceneFeedback + MMF_Player(target: ScreenOverlay.CanvasGroup)
└── FeedbackFadeIn ← SceneFeedback + MMF_Player(target: ScreenOverlay.CanvasGroup)
4.2 SplashScreenController:美术资源替换
脚手架已创建 StudioLogo 和 GameTitle 子节点(带 CanvasGroup),默认为空。
| 子节点 | 需要添加 | 说明 |
|---|---|---|
StudioLogo |
Image 组件 + 工作室 Logo 贴图 |
设置 Preserve Aspect = true |
GameTitle |
Image 组件 + 游戏标题图 |
同上 |
时序参数(可在 SplashScreenController Inspector 中调整):
| 字段 | 默认值 | 说明 |
|---|---|---|
_fadeInDuration |
0.8 s |
每个 Logo 的淡入时长 |
_holdDuration |
1.5 s |
停留时长 |
_fadeOutDuration |
0.6 s |
淡出时长 |
_stageGapDuration |
0.3 s |
两段演出之间的间隔 |
4.3 LoadingScreenManager:背景图与提示文字
脚手架已创建进度条 Image 和 TipText,以下字段仍需手动填写:
| 字段 | 类型 | 说明 |
|---|---|---|
_backgroundArts |
Image[] |
加载画面随机背景图数组,留空则无背景 |
_tipMessages |
string[] |
本地化 key 列表(对应 Localization UI 表),留空则不显示提示文字 |
_minDisplayTime |
float(默认 0.5 s) |
加载极快时的最短显示时间,避免画面闪烁 |
进度条设置确认:
ProgressBarFill Image 已由脚手架设置为 Image.Type = Filled、FillMethod = Horizontal。
确认 Fill Origin = Left,并将图片 Import Settings 的 Wrap Mode 设为 Clamp。
4.4 HUDController:UI 资源绑定
HUDController 依赖较多图标/文本/进度条 Prefab,均需在 Inspector 手动绑定。
具体字段参见 Assets/_Game/Scripts/UI/HUD/HUDController.cs 中的 [SerializeField] 注释。
HUD 资源较多,建议参考美术规范文档
Docs/Design/UI_HUD_Spec.md(如已存在)进行配置。
4.5 AudioManager:AudioMixer 指定
节点: [SERVICES] → AudioManager
| 字段 | 说明 |
|---|---|
_mixer |
拖入 Assets/_Game/Audio/MainMixer.mixer(或对应的 AudioMixer 资产) |
_masterVolumeParam |
AudioMixer 中 Master 音量参数名(默认 "MasterVolume") |
_bgmVolumeParam |
BGM 音量参数名(默认 "BGMVolume") |
_sfxVolumeParam |
SFX 音量参数名(默认 "SFXVolume") |
脚手架已自动创建 2 个 BGM Source 和 6 个 SFX Source 并绑定。
4.6 PauseMenuController:按钮文本与样式
脚手架已创建 4 个按钮子节点(Btn_Resume / Btn_Settings / Btn_MainMenu / Btn_Quit),但节点仅含 Button 组件,没有视觉内容。
每个按钮需要添加:
Image组件(或替换为TextMeshProUGUI子节点作为标签)- 根据 UI 设计规范配置 Sprite / 颜色 / Navigation
5. 事件频道速查表
以下是 Persistent 场景相关的全部事件频道。
所有资产由 BaseGames → Scene → Setup → Create All Event Channel Assets 自动生成到 Assets/_Game/Events/。
| SO 名称 | 类型 | 发布者 | 订阅者 |
|---|---|---|---|
EVT_FadeOutRequest |
VoidEventChannelSO | SceneService | SceneFadeController |
EVT_FadeInRequest |
VoidEventChannelSO | SceneService | SceneFadeController |
EVT_LoadingStarted |
VoidEventChannelSO | SceneService / SceneLoader | LoadingScreenManager |
EVT_LoadingComplete |
VoidEventChannelSO | SceneService / SceneLoader | LoadingScreenManager |
EVT_LoadingProgressUpdated |
FloatEventChannelSO | SceneLoader | LoadingScreenManager |
EVT_SplashStartRequest |
VoidEventChannelSO | BootSequencer | SplashScreenController |
EVT_SplashComplete |
VoidEventChannelSO | SplashScreenController | BootSequencer |
EVT_SceneLoadRequest |
SceneLoadRequestEventChannelSO | DoorTransition / RoomTransition / PauseMenuController | SceneService |
EVT_GameStateChanged |
GameStateEventChannelSO | GameManager | UIManager |
EVT_PauseRequested |
VoidEventChannelSO | InputHandler | UIManager |
EVT_DeathScreenConfirmed |
VoidEventChannelSO | DeathScreenController | DeathRespawnService |
EVT_ResumeRequested |
VoidEventChannelSO | PauseMenuController | GameManager |
6. 场景切换完整时序
玩家触碰门触发器
│
├─ DoorTransition.OnTriggerEnter2D()
│ └─ ServiceLocator<ISceneService>.Get().RequestTransition(request)
│
└─ SceneService.LoadSceneCoroutine()
│
├─ 1. EVT_FadeOutRequest.Raise()
│ └─ SceneFadeController → FeedbackFadeOut.Play()
│ └─ MMF_Player → 画面变黑(≤ 0.4 s)
│
├─ 2. yield WaitForSeconds(_sceneFadeDuration) ← 等待黑幕完成
│
├─ 3. [可选] EVT_LoadingStarted.Raise()
│ └─ LoadingScreenManager.Show()
│
├─ 4. UnloadOldScene / LoadNewScene(Addressables)
│
├─ 5. [可选] EVT_LoadingComplete.Raise()
│ └─ LoadingScreenManager.Hide()
│
└─ 6. EVT_FadeInRequest.Raise()
└─ SceneFadeController → FeedbackFadeIn.Play()
└─ MMF_Player → 画面显现(≤ 0.4 s)
7. 常见问题排查
Q:运行后画面直接跳转,没有淡入淡出效果
原因: FeedbackFadeOut / FeedbackFadeIn 的 MMF_Player 中没有添加任何 Feedback。
解决: 参见 4.1 节 添加 Canvas Group Alpha Feedback。
Q:淡出动画播放到一半画面就跳转了
原因: MMF_Player 总时长超过了 SceneService._sceneFadeDuration(默认 0.4 s)。
解决: 缩短 MMF_Player 的 Duration,或在 SceneService Inspector 中加大 _sceneFadeDuration。
Q:脚手架运行后报告显示某事件频道未找到
原因: 事件频道资产尚未生成。
解决: 先执行 BaseGames → Scene → Setup → Create All Event Channel Assets,再重新运行 Scaffold Persistent Scene。
Q:UIManager 的 _panels 数组为空
原因: 可能在旧版本的 Persistent 场景上重新运行了脚手架(幂等逻辑生效,但 _panels 已存在数据)。
解决: 在 Inspector 中展开 UIManager._panels,确认 4 个条目(Pause / Settings / Map / Shop)及其 root 引用均正确指向对应的 GameObject。
Q:暂停菜单打开后按钮没有响应
可能原因 1: _onResumeRequested 未绑定(脚手架未找到对应 SO)。检查 PauseMenuController Inspector。
可能原因 2: EventSystem 缺失。确认 Persistent 场景中存在 EventSystem GameObject(脚手架会自动创建)。