# 基础教程 这是一个完整的从零开始的教程,将带领你创建一个使用 GFramework 的简单的计数器应用。 ## 目录 - [环境准备](#环境准备) - [项目创建](#项目创建) - [项目初始化](#项目初始化) - [功能实现](#功能实现) - [测试验证](#测试验证) ## 环境准备 ### 系统要求 - **操作系统**: Windows 10+, macOS 10.15+, 或 Linux - **.NET SDK**: 6.0 或更高版本 - **Godot 引擎**: 4.5.1 或更高版本 - **IDE**: Visual Studio 2022+, JetBrains Rider, 或 VS Code ### 安装 .NET SDK 1. 访问 [.NET 官网](https://dotnet.microsoft.com/download) 2. 下载并安装 .NET 6.0 SDK 3. 验证安装: ```bash dotnet --version # 应该显示 6.0.x 或更高版本 ``` ### 安装 Godot 1. 访问 [Godot 官网](https://godotengine.org/download) 2. 下载 Godot (Mono版) 3. 解压到合适的位置并启动 4. 在编辑器设置中确认 .NET 支持 ### 验证环境 创建一个测试项目验证环境: ```bash # 创建测试项目 dotnet new console -n TestProject cd TestProject # 如果使用 Godot,添加 Godot 引用 dotnet add package GeWuYou.GFramework.Core dotnet add package GeWuYou.GFramework.Godot # 编译测试 dotnet build ``` ## 项目创建 ### 1. 创建新的 Godot 项目 1. 打开 Godot 编辑器 2. 点击 "新建项目" 3. 创建项目文件夹,命名为 "MyGFrameworkGame" 4. 创建项目后初始化C#项目 ![image-20260211210657387](assets/basic-tutorial/image-20260211210657387.png) ### 2. 配置项目结构 在项目根目录创建以下文件夹结构: ``` MyGFrameworkGame/ ├── sripts/ # 脚本 ├── scenes/ # 场景 ├── assets/ # 游戏资源 ├── global/ # 全局类 └── project.godot ``` 当然,你也可以选择你喜欢的代码组织方式 ### 3. 引入GFramework 一般我们有两种引入方式 第一种是使用命令的方式引入 ```sh # 核心能力(推荐最小起步) dotnet add package GeWuYou.GFramework.Core dotnet add package GeWuYou.GFramework.Core.Abstractions # 游戏扩展 dotnet add package GeWuYou.GFramework.Game dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成(仅 Godot 项目需要) dotnet add package GeWuYou.GFramework.Godot # 源码生成器(可选,但推荐) dotnet add package GeWuYou.GFramework.SourceGenerators ``` 当然这样包太多了,太费劲了,因此可以通过下方的命令直接将Core和Game模块都引入到项目中,再通过另外两个引入godot支持和源代码生成器 ```sh # Core+Game dotnet add package GeWuYou.GFramework # Godot dotnet add package GeWuYou.GFramework.Godot # 源码生成器 dotnet add package GeWuYou.GFramework.SourceGenerators ``` 第二种方法可以通过ide(比如VS和Rider) 它们都提供NuGet管理,允许你基于图形界面来搜索并下载相关的NuGet包 ![image-20260211211756993](assets/basic-tutorial/image-20260211211756993.png) ## 项目初始化 ### 1. 定义游戏架构 创建 `scripts/architecture/GameArchitecture.cs`: ```csharp using GFramework.Godot.architecture; namespace MyGFrameworkGame.scripts.architecture; public class GameArchitecture : AbstractArchitecture { protected override void InstallModules() { } } ``` 游戏架构类提供一个InstallModules方法用于注册模块,模块可以看作是一个个相关的Model、System、Utility的集合,按照开发者的意愿进行组织。 这里以一个示例代码进行说明 ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.environment; using GFramework.Godot.architecture; using GFrameworkGodotTemplate.scripts.module; namespace GFrameworkGodotTemplate.scripts.core; /// /// 游戏架构类,负责安装和管理游戏所需的各种模块 /// 继承自AbstractArchitecture,用于构建游戏的整体架构体系 /// public sealed class GameArchitecture(IArchitectureConfiguration configuration, IEnvironment environment) : AbstractArchitecture(configuration, environment) { public IArchitectureConfiguration Configuration { get; set; } = configuration; /// /// 安装游戏所需的各个功能模块 /// 该方法在架构初始化时被调用,用于注册系统、模型和工具模块 /// protected override void InstallModules() { // 安装数据模型相关的Godot模块 InstallModule(new ModelModule()); // 安装系统相关的Godot模块 InstallModule(new SystemModule()); // 安装工具类相关的Godot模块 InstallModule(new UtilityModule()); // 安装状态相关的Godot模块 InstallModule(new StateModule()); } } ``` 从这里可以看到我们把 Model、 System、 Utility 进行了拆分,这是一种方式,使用这种方式的前提是,项目依赖不复杂,如果项目依赖复杂可能就得拆分多个Module来控制初始化顺序 ### 2. 创建模型模块 创建 `scripts/module/ModelModule.cs`: ```csharp using GFramework.Core.Abstractions.architecture; using GFramework.Game.architecture; namespace MyGFrameworkGame.scripts.module; public class ModelModule: AbstractModule { public override void Install(IArchitecture architecture) { } } ``` 这个Install(IArchitecture architecture)方法用于注册所需要的类即各种model > Model在框架中表示游戏的状态和数据。模型是简单的数据容器,它们公开描述游戏实体当前状态的属性。 这里以一个示例代码进行说明 ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Core.functional.pipe; using GFramework.Game.Abstractions.data; using GFramework.Game.architecture; using GFramework.Game.setting; using GFramework.Godot.setting; using GFramework.Godot.setting.data; using GFrameworkGodotTemplate.scripts.setting; namespace GFrameworkGodotTemplate.scripts.module; /// /// ModelModule 类继承自 AbstractModule,用于在架构中安装和注册模型。 /// 该模块主要负责初始化设置相关的模型,并将其注册到架构中。 /// public class ModelModule : AbstractModule { /// /// 安装方法,用于将模型注册到指定的架构中。 /// /// IArchitecture 接口实例,表示当前的应用程序架构。 public override void Install(IArchitecture architecture) { // 获取设置数据仓库的实例,用于后续模型的初始化 var settingsDataRepository = architecture.Context.GetUtility()!; // 注册设置模型,并配置其应用器(Applicator) architecture.RegisterModel( new SettingsModel(new SettingDataLocationProvider(), settingsDataRepository) .Also(it => { // 注册音频设置应用器,用于处理音频相关配置 it.RegisterApplicator(new GodotAudioSettings(it, new AudioBusMap())) // 注册图形设置应用器,用于处理图形相关配置 .RegisterApplicator(new GodotGraphicsSettings(it)) // 注册本地化设置应用器,用于处理语言和区域相关配置 .RegisterApplicator(new GodotLocalizationSettings(it, new LocalizationMap())); }) ); } } ``` 可以看到这里把设置数据模型注册进了架构中 ### 3. 创建系统模块 创建 `scripts/module/SystemModule.cs`: ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Game.architecture; namespace MyGFrameworkGame.scripts.module; public class SystemModule: AbstractModule { public override void Install(IArchitecture architecture) { } } ``` 这个Install(IArchitecture architecture)方法用于注册所需要的类即各种system > System 包含游戏的业务逻辑和规则。系统操作模型并实现核心机制,如战斗、物理、库存管理或进度系统。 这里以一个示例代码进行说明 ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Game.architecture; using GFramework.Game.setting; using GFrameworkGodotTemplate.scripts.core.scene; using GFrameworkGodotTemplate.scripts.core.ui; namespace GFrameworkGodotTemplate.scripts.module; /// /// 系统Godot模块类,负责安装和注册游戏所需的各种系统组件 /// 继承自AbstractGodotModule,用于在游戏架构中集成系统功能 /// public class SystemModule : AbstractModule { /// /// 安装方法,用于向游戏架构注册各种系统组件 /// /// 游戏架构接口实例,用于注册系统 public override void Install(IArchitecture architecture) { architecture.RegisterSystem(new UiRouter()); architecture.RegisterSystem(new SceneRouter()); architecture.RegisterSystem(new SettingsSystem()); } } ``` 可以看到我们向框架里注册了ui路由,场景路由,设置系统,这便是系统模块的作用 ### 4. 创建工具模块 创建 `scripts/module/UtilityModule.cs`: ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Game.architecture; namespace MyGFrameworkGame.scripts.module; public class UtilityModule: AbstractModule { public override void Install(IArchitecture architecture) { } } ``` 同理这个Install(IArchitecture architecture)方法用于注册所需要的类即各种utility > Utility 提供可在整个应用程序中使用的无状态辅助函数和算法——数学计算、路径查找、数据验证和其他纯函数。 这里以一个示例代码进行说明 ```C# using GFramework.Core.Abstractions.architecture; using GFramework.Game.Abstractions.data; using GFramework.Game.architecture; using GFramework.Game.data; using GFramework.Game.serializer; using GFramework.Godot.scene; using GFramework.Godot.storage; using GFramework.Godot.ui; using GFrameworkGodotTemplate.scripts.data; using GFrameworkGodotTemplate.scripts.utility; using Godot; namespace GFrameworkGodotTemplate.scripts.module; /// /// 工具模块类,负责安装和管理游戏中的实用工具组件 /// public class UtilityModule : AbstractModule { /// /// 安装模块到指定的游戏架构中 /// /// 要安装模块的目标游戏架构实例 public override void Install(IArchitecture architecture) { architecture.RegisterUtility(new GodotUiRegistry()); architecture.RegisterUtility(new GodotSceneRegistry()); architecture.RegisterUtility(new GodotTextureRegistry()); architecture.RegisterUtility(new GodotUiFactory()); var jsonSerializer = new JsonSerializer(); architecture.RegisterUtility(jsonSerializer); var storage = new GodotFileStorage(jsonSerializer); architecture.RegisterUtility(storage); architecture.RegisterUtility(new UnifiedSettingsDataRepository(storage, jsonSerializer, new DataRepositoryOptions { BasePath = ProjectSettings.GetSetting("application/config/save/setting_path").AsString(), AutoBackup = true })); architecture.RegisterUtility(new SaveStorageUtility()); } } ``` 这里安装了非常多的工具,特别是对于工具之间相互依赖的情况下,集中处理是一种比较好的方式。 ### 5. 创建游戏入口点 在Godot创建一个全局类GameEntryPoint.cs ![image-20260211222402064](assets/basic-tutorial/image-20260211222402064.png) 全局类代码 ```C# using GFramework.Core.Abstractions.architecture; using Godot; using MyGFrameworkGame.scripts.architecture; namespace MyGFrameworkGame.global; /// /// 游戏入口点类,继承自Node类。 /// 该类负责初始化游戏架构,并在节点首次进入场景树时执行相关逻辑。 /// public partial class GameEntryPoint : Node { /// /// 获取游戏架构的静态属性。 /// 该属性在类初始化时被赋值,用于全局访问游戏架构实例。 /// public static IArchitecture Architecture { get; private set; } = null!; /// /// 当节点首次进入场景树时调用此方法。 /// 在此方法中,创建并初始化游戏架构实例。 /// public override void _Ready() { // 创建游戏架构实例 Architecture = new GameArchitecture(); // 初始化游戏架构 Architecture.Initialize(); } } ``` ### 6. 安装模块 ```C# using GFramework.Godot.architecture; using MyGFrameworkGame.scripts.module; namespace MyGFrameworkGame.scripts.architecture; /// /// 游戏架构类,继承自抽象架构类 AbstractArchitecture。 /// 负责安装和管理游戏中的各个模块。 /// public class GameArchitecture : AbstractArchitecture { /// /// 安装游戏所需的模块。 /// 该方法在架构初始化时被调用,用于注册模型、系统和工具模块。 /// protected override void InstallModules() { // 安装模型模块,负责处理游戏数据和业务逻辑 InstallModule(new ModelModule()); // 安装系统模块,负责处理游戏的核心系统功能 InstallModule(new SystemModule()); // 安装工具模块,提供通用的辅助功能和工具方法 InstallModule(new UtilityModule()); } } ``` 这样我们的准备工作就完成了 ## 功能实现 ### 1. 实现基础功能 首先让我们搭建一个非常简单的场景 ![image-20260211215031192](assets/basic-tutorial/image-20260211215031192.png) 这个是大致结构 ![image-20260211214905664](assets/basic-tutorial/image-20260211214905664.png) 这个是效果图 接着我们创建对应的代码 ```C# using GFramework.Core.Abstractions.controller; using GFramework.SourceGenerators.Abstractions.logging; using GFramework.SourceGenerators.Abstractions.rule; using Godot; namespace MyGFrameworkGame.scripts.app; /// /// App 类继承自 Control 并实现 IController 接口,用于管理应用程序的核心逻辑。 /// 该类通过按钮控制计数器的增减,并更新界面上的标签显示。 /// [ContextAware] [Log] public partial class App : Control, IController { /// /// 获取场景中的 AddButton 节点,用于增加计数器值。 /// private Button AddButton => GetNode