--- title: Godot 暂停处理 description: Godot 暂停处理系统提供了 GFramework 暂停管理与 Godot SceneTree 暂停的完整集成。 --- # Godot 暂停处理 ## 概述 Godot 暂停处理系统是 GFramework.Godot 中连接框架暂停管理与 Godot 引擎暂停机制的核心组件。它提供了暂停栈管理、分组暂停、嵌套暂停等功能,让你可以在 Godot 项目中使用 GFramework 的暂停系统。 通过 Godot 暂停处理系统,你可以实现精细的暂停控制,支持游戏逻辑暂停、UI 暂停、动画暂停等多种场景,同时保持与 Godot SceneTree 暂停机制的完美兼容。 **主要特性**: - 暂停栈管理(支持嵌套暂停) - 分组暂停(Global、Gameplay、Animation、Audio 等) - 与 Godot SceneTree.Paused 集成 - 暂停处理器机制 - 暂停作用域(支持 using 语法) - 线程安全的暂停管理 ## 核心概念 ### 暂停栈管理器 `IPauseStackManager` 管理游戏中的暂停状态: ```csharp public interface IPauseStackManager : IContextUtility { // 推入暂停请求 PauseToken Push(string reason, PauseGroup group = PauseGroup.Global); // 弹出暂停请求 bool Pop(PauseToken token); // 查询是否暂停 bool IsPaused(PauseGroup group = PauseGroup.Global); // 获取暂停深度 int GetPauseDepth(PauseGroup group = PauseGroup.Global); // 暂停状态变化事件 event EventHandler? OnPauseStateChanged; } ``` ### 暂停组 `PauseGroup` 定义不同的暂停作用域: ```csharp public enum PauseGroup { Global = 0, // 全局暂停(影响所有系统) Gameplay = 1, // 游戏逻辑暂停(不影响 UI) Animation = 2, // 动画暂停 Audio = 3, // 音频暂停 Custom1 = 10, // 自定义组 1 Custom2 = 11, // 自定义组 2 Custom3 = 12 // 自定义组 3 } ``` ### 暂停令牌 `PauseToken` 唯一标识一个暂停请求: ```csharp public readonly struct PauseToken { public Guid Id { get; } public bool IsValid { get; } } ``` ### Godot 暂停处理器 `GodotPauseHandler` 响应暂停栈状态变化,控制 SceneTree.Paused: ```csharp public class GodotPauseHandler : IPauseHandler { public int Priority => 0; public void OnPauseStateChanged(PauseGroup group, bool isPaused) { // 只有 Global 组影响 Godot 的全局暂停 if (group == PauseGroup.Global) { _tree.Paused = isPaused; } } } ``` ## 基本用法 ### 设置暂停系统 ```csharp using GFramework.Godot.Architecture; using GFramework.Godot.Pause; using GFramework.Core.Pause; public class GameArchitecture : AbstractArchitecture { protected override void InstallModules() { // 注册暂停栈管理器 var pauseManager = new PauseStackManager(); RegisterUtility(pauseManager); // 注册 Godot 暂停处理器 var pauseHandler = new GodotPauseHandler(GetTree()); pauseManager.RegisterHandler(pauseHandler); } } ``` ### 基本暂停和恢复 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class PauseMenu : Control { private PauseToken _pauseToken; public void ShowPauseMenu() { // 暂停游戏 var pauseManager = this.GetUtility(); _pauseToken = pauseManager.Push("Pause menu opened"); Show(); } public void HidePauseMenu() { // 恢复游戏 var pauseManager = this.GetUtility(); pauseManager.Pop(_pauseToken); Hide(); } } ``` ### 使用暂停作用域 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class DialogBox : Control { public async void ShowDialog() { var pauseManager = this.GetUtility(); // 使用 using 语法自动管理暂停 using (pauseManager.PauseScope("Dialog shown")) { Show(); await ToSignal(GetTree().CreateTimer(3.0f), "timeout"); Hide(); } // 自动恢复 } } ``` ### 查询暂停状态 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class GameController : Node { public override void _Process(double delta) { var pauseManager = this.GetUtility(); // 检查是否暂停 if (pauseManager.IsPaused()) { GD.Print("游戏已暂停"); return; } // 游戏逻辑 UpdateGame(delta); } private void UpdateGame(double delta) { // 游戏更新逻辑 } } ``` ## 高级用法 ### 分组暂停 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class GameManager : Node { private PauseToken _gameplayPauseToken; private PauseToken _animationPauseToken; // 只暂停游戏逻辑,UI 仍然可以交互 public void PauseGameplay() { var pauseManager = this.GetUtility(); _gameplayPauseToken = pauseManager.Push("Gameplay paused", PauseGroup.Gameplay); } public void ResumeGameplay() { var pauseManager = this.GetUtility(); pauseManager.Pop(_gameplayPauseToken); } // 只暂停动画 public void PauseAnimations() { var pauseManager = this.GetUtility(); _animationPauseToken = pauseManager.Push("Animations paused", PauseGroup.Animation); } public void ResumeAnimations() { var pauseManager = this.GetUtility(); pauseManager.Pop(_animationPauseToken); } // 检查特定组的暂停状态 public bool IsGameplayPaused() { var pauseManager = this.GetUtility(); return pauseManager.IsPaused(PauseGroup.Gameplay); } } ``` ### 嵌套暂停 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class GameScene : Node { public async void ShowNestedDialogs() { var pauseManager = this.GetUtility(); // 第一层暂停 using (pauseManager.PauseScope("First dialog")) { GD.Print($"暂停深度: {pauseManager.GetPauseDepth()}"); // 输出: 1 ShowDialog("第一个对话框"); await ToSignal(GetTree().CreateTimer(2.0f), "timeout"); // 第二层暂停 using (pauseManager.PauseScope("Second dialog")) { GD.Print($"暂停深度: {pauseManager.GetPauseDepth()}"); // 输出: 2 ShowDialog("第二个对话框"); await ToSignal(GetTree().CreateTimer(2.0f), "timeout"); } GD.Print($"暂停深度: {pauseManager.GetPauseDepth()}"); // 输出: 1 } GD.Print($"暂停深度: {pauseManager.GetPauseDepth()}"); // 输出: 0 } private void ShowDialog(string message) { GD.Print(message); } } ``` ### 自定义暂停处理器 ```csharp using GFramework.Core.Abstractions.Pause; using Godot; // 自定义动画暂停处理器 public class AnimationPauseHandler : IPauseHandler { private readonly AnimationPlayer _animationPlayer; public AnimationPauseHandler(AnimationPlayer animationPlayer) { _animationPlayer = animationPlayer; } public int Priority => 10; public void OnPauseStateChanged(PauseGroup group, bool isPaused) { // 只响应 Animation 组 if (group == PauseGroup.Animation) { if (isPaused) { _animationPlayer.Pause(); GD.Print("动画已暂停"); } else { _animationPlayer.Play(); GD.Print("动画已恢复"); } } } } // 注册自定义处理器 public partial class GameController : Node { public override void _Ready() { var pauseManager = this.GetUtility(); var animationPlayer = GetNode("AnimationPlayer"); var animationHandler = new AnimationPauseHandler(animationPlayer); pauseManager.RegisterHandler(animationHandler); } } ``` ### 音频暂停处理器 ```csharp using GFramework.Core.Abstractions.Pause; using Godot; public class AudioPauseHandler : IPauseHandler { private readonly AudioStreamPlayer _musicPlayer; private readonly AudioStreamPlayer _sfxPlayer; public AudioPauseHandler(AudioStreamPlayer musicPlayer, AudioStreamPlayer sfxPlayer) { _musicPlayer = musicPlayer; _sfxPlayer = sfxPlayer; } public int Priority => 20; public void OnPauseStateChanged(PauseGroup group, bool isPaused) { if (group == PauseGroup.Audio || group == PauseGroup.Global) { if (isPaused) { _musicPlayer.StreamPaused = true; _sfxPlayer.StreamPaused = true; } else { _musicPlayer.StreamPaused = false; _sfxPlayer.StreamPaused = false; } } } } ``` ### 节点暂停模式控制 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class GameNode : Node { public override void _Ready() { // 设置节点在暂停时的行为 // 暂停时停止处理 ProcessMode = ProcessModeEnum.Pausable; // 暂停时继续处理(用于 UI) // ProcessMode = ProcessModeEnum.Always; // 暂停时停止,且子节点也停止 // ProcessMode = ProcessModeEnum.Inherit; } public override void _Process(double delta) { // 当 SceneTree.Paused = true 且 ProcessMode = Pausable 时 // 此方法不会被调用 UpdateGameLogic(delta); } private void UpdateGameLogic(double delta) { // 游戏逻辑 } } ``` ### UI 在暂停时继续工作 ```csharp using Godot; using GFramework.Godot.Extensions; public partial class PauseMenuUI : Control { public override void _Ready() { // UI 在游戏暂停时仍然可以交互 ProcessMode = ProcessModeEnum.Always; GetNode