# StrayFog 框架业务开发指南 ## 一、开发前准备 ### 1.1 核心概念理解 #### 1.1.1 框架层级关系 ``` ┌─────────────────────────────────────────────────────────────┐ │ 开发层级视图 │ ├─────────────────────────────────────────────────────────────┤ │ 业务层 (你开发的代码) │ │ ├── UI界面、业务逻辑、游戏数据 │ │ │ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ │ 核心库 (只读,框架团队维护) │ │ │ │ │ ├── Core: 模拟行为、全局数据 │ │ │ │ │ ├── HF: 资源管理、事件系统、相机管理 │ │ │ │ │ └── General: 状态机、工具类 │ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` #### 1.1.2 核心库访问原则 | 原则 | 说明 | |-----|-----| | **只读访问** | 核心库代码只可读取,不可修改 | | **接口优先** | 通过接口访问服务,而非直接实例化实现类 | | **继承扩展** | 通过继承抽象类实现自定义逻辑 | | **依赖注入** | 通过管理器获取实例,而非硬编码 | --- ## 二、业务代码结构 ### 2.1 目录组织规范 ``` Assets/Game/GameHFScripte/GameFunction/ ├── Event/ # 消息处理 │ ├── ServerToClient/ # 服务器到客户端消息 │ ├── ClientToClient/ # 客户端内部消息 │ └── Handle/ # 消息处理器 ├── GameRoot/ # 框架调用入口 │ ├── HFGameStart.cs # 热更新进入入口 │ ├── HFFunCatalogue.cs # 框架统一调用入口 │ ├── HFFunCatalogue_Function.cs # 功能调用方法 │ └── ... ├── HFDownLoadSubPackage/ # 分包下载 │ ├── HFSubPackageManager.cs # 分包管理器 │ ├── HFGameStartAssetsCheckManager.cs # 资源检查 │ └── ... ├── HFExtends/ # Class扩展方法 │ ├── UI/ # UI扩展 │ ├── Material/ # 材质扩展 │ ├── String/ # 字符串扩展 │ └── ... ├── Logic/ # 游戏主要业务逻辑(存放各功能Manager) │ ├── User/ # 用户相关 │ ├── Login/ # 登录系统 │ ├── Fight/ # 战斗系统 │ ├── CardDeck/ # 卡组系统 │ ├── Bag/ # 背包系统 │ └── ... ├── UIWindows/ # UI窗口业务逻辑 │ ├── Login/ # 登录窗口 │ ├── Lobby/ # 大厅窗口 │ ├── Fight/ # 战斗窗口 │ ├── Shop/ # 商店窗口 │ └── ... ├── GameEntity/ # 游戏实体 │ ├── Entity/ # 实体定义 │ ├── EntityPool/ # 实体对象池 │ └── ... ├── SoundManagerPro/ # 音效管理 ├── SceneManager/ # 场景管理 ├── SDK/ # SDK集成 └── MonoCompent/ # Mono组件 ``` ### 2.2 文件命名规范 | 文件类型 | 命名规则 | 示例 | |---------|---------|-----| | **窗口类** | `XXXWindow.cs` | `LoginWindow.cs` | | **组件类** | `XXXComponent.cs` | `ItemCellComponent.cs` | | **管理器类** | `XXXManager.cs` | `UIManager.cs` | | **数据类** | `XXXData.cs` | `PlayerData.cs` | | **配置类** | `XXXConfig.cs` | `SkillConfig.cs` | --- ## 三、核心库使用指南 ### 3.1 对象池使用 #### 3.1.1 GameObject对象池 ```csharp public class BulletManager : MonoBehaviour { [SerializeField] private GameObject bulletPrefab; private HFObjectMemPool m_BulletPool; void Awake() { // 创建对象池 m_BulletPool = new HFObjectMemPool(bulletPrefab, transform); } public void Fire(Vector3 position, Quaternion rotation) { bool isNew; GameObject bullet = m_BulletPool.GetItem(out isNew); bullet.transform.position = position; bullet.transform.rotation = rotation; // 如果是新创建的对象,初始化组件 if (isNew) { bullet.GetComponent().Initialize(); } } public void RecycleBullet(GameObject bullet) { m_BulletPool.GiveBack(bullet); } void OnDestroy() { // 清理对象池 m_BulletPool.Recycle(); } } ``` #### 3.1.2 脚本对象池 ```csharp public class EventArgPool : MonoBehaviour { private HFScriptMemPool m_ArgPool; void Awake() { m_ArgPool = new HFScriptMemPool(); } public GameEventArgs GetEventArgs(GameEventId eventId) { bool isNew; GameEventArgs arg = m_ArgPool.GetItem(out isNew); arg.eventId = eventId; return arg; } public void RecycleEventArgs(GameEventArgs arg) { m_ArgPool.GiveBack(arg); } } ``` ### 3.2 事件系统使用 #### 3.2.1 定义事件枚举和参数 ```csharp // 事件ID枚举 public enum GameEventId { PlayerLevelUp, EnemyKilled, GoldChanged } // 事件参数基类 public class GameEventArgs : IHFEventArg, IHFRecycle { public GameEventId eventId { get; set; } public void Recycle() { // 重置状态 eventId = default; } } // 具体事件参数 public class PlayerLevelUpEventArgs : GameEventArgs { public int playerId; public int oldLevel; public int newLevel; } ``` #### 3.2.2 注册和触发事件 **事件系统分为两类**: - **STCEvent**:Server To Client(服务器到客户端消息) - **CTCEvent**:Client To Client(客户端内部消息) **注册事件监听**: ```csharp /// /// 卡组窗口 /// [HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/CardDeck/CardDeckWindow.prefab")] [HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Dynamic, isIgnoreCloseByESC = false)] public class CardDeckWindow : AbsHFUIWindow { /// /// 初始化(仅调用一次) /// protected override void OnRunAwake() { base.OnRunAwake(); // 初始化UI组件引用 // 绑定事件监听(如按钮点击等) } /// /// 打开窗口(每次打开调用) /// protected override void OnOpen(Action _onOpenComplete) { base.OnOpen(_onOpenComplete); // 注册客户端内部消息监听(CTCEvent) HFFunCatalogue.Event.CTCEvent.AddListener(enHFCTCEvent.CardUpdate, OnCardUpdate); } /// /// 关闭窗口 /// protected override void OnClose(Action _onCloseComplete) { base.OnClose(_onCloseComplete); // 取消客户端内部消息监听 HFFunCatalogue.Event.CTCEvent.RemoveListener(enHFCTCEvent.CardUpdate, OnCardUpdate); } void OnCardUpdate(HFEventArgBase arg) { HFEvent_CTC_CardUpdate cardArg = arg as HFEvent_CTC_CardUpdate; // 更新卡组UI显示 } } ``` > **注意**:UI窗口中**不监听服务器事件(STCEvent)**,服务器事件应在Logic层的Manager中监听。 **Manager类型定义**: Manager需要继承`AbsHFSingleMonoBehaviour`或`AbsHFSingleRunTime`: | 类型 | 说明 | 适用场景 | |-----|------|---------| | `AbsHFSingleMonoBehaviour` | 生成GameObject,可注册MonoBehaviour事件 | 需要Update/FixedUpdate等生命周期 | | `AbsHFSingleRunTime` | 纯内存单例,无GameObject | 不需要生命周期事件 | **示例1:使用AbsHFSingleMonoBehaviour(需要Update)** ```csharp public class PlayerManager : AbsHFSingleMonoBehaviour { /// /// 注册模拟Behaviour事件 /// 通过此属性声明需要监听的事件 /// protected override int[] simulateBehaviourEvents => new int[] { enHFSimulateBehaviourEvent.Mono_Update, enHFSimulateBehaviourEvent.Mono_FixedUpdate }; /// /// 单例创建时调用(仅一次) /// protected override void OnAfterCreateInstance() { base.OnAfterCreateInstance(); // 初始化逻辑 RegisterServerEvents(); } /// /// 模拟Update事件(通过simulateBehaviourEvents注册后自动调用) /// 注:这是封装后的事件,非Unity原生MonoBehaviour.Update /// protected override void OnRunUpdate() { // 每帧更新逻辑 } /// /// 模拟FixedUpdate事件 /// protected override void OnRunFixedUpdate() { // 物理更新逻辑 } /// /// 注册服务器事件监听 /// void RegisterServerEvents() { HFFunCatalogue.Event.STCEvent.AddListener(enHFSTCEvent.PlayerInfo, OnPlayerInfo); } void OnPlayerInfo(HFEventArgBase arg) { HFEvent_STC_PlayerInfo info = arg as HFEvent_STC_PlayerInfo; // 处理服务器返回的玩家信息 // 触发客户端事件通知UI更新 HFEvent_CTC_PlayerLevelUp evt = HFFunCatalogue.New(); evt.playerId = info.playerId; evt.newLevel = info.level; HFFunCatalogue.Event.CTCEvent.Dispatch(evt); } } ``` **示例2:使用AbsHFSingleRunTime(纯逻辑)** ```csharp public class ConfigManager : AbsHFSingleRunTime { /// /// 单例创建时调用(仅一次) /// protected override void OnAfterCreateInstance() { base.OnAfterCreateInstance(); // 加载配置表 LoadConfigTables(); } void LoadConfigTables() { // 加载配置数据 } } ``` ### 3.3 资源加载使用 #### 3.3.1 加载AssetBundle资源 ```csharp public class ResourceLoader : MonoBehaviour { public void LoadPlayerModel(int resId, Action onLoaded) { // 通过HFFunCatalogue统一入口加载资源 // resId: 从Res配置表中读取的资源ID HFFunCatalogue.Asset.LoadAsset(resId, (res, obj) => { if (obj != null) { GameObject model = res.GetAsset(); onLoaded?.Invoke(model); } else { Debug.LogError($"加载失败: resId={resId}"); } }); } } ``` **实体资源加载示例**: ```csharp // 在Entity中加载资源 HFFunCatalogue.Asset.LoadAsset(data.EntityRes.Id, (res, obj) => { if (!entity.isDeath) { var Boddy = res.GetAsset(); data.SetBoddy(Boddy); } }); ``` ### 3.4 相机管理使用 #### 3.4.1 创建自定义相机 ```csharp public class UIOverlayCamera : AbsHFCameraItem { [SerializeField] private Camera uiCamera; [SerializeField] private int weight = 10; public override Camera CameraItem => uiCamera; public override int Weight => weight; protected override void OnInitialize() { base.OnInitialize(); // 自定义初始化逻辑 uiCamera.clearFlags = CameraClearFlags.Depth; uiCamera.depth = 100; } } ``` #### 3.4.2 管理相机堆栈 ```csharp public class CameraController : MonoBehaviour { void Start() { // 获取相机管理器 HFCameraManager cameraMgr = HFCameraManager.Instance; // 添加自定义相机 UIOverlayCamera uiCamera = GetComponent(); cameraMgr.AddCamera(uiCamera); // 获取主相机 Camera mainCam = cameraMgr.mainCamera.MainCamera; } void OnDestroy() { UIOverlayCamera uiCamera = GetComponent(); HFCameraManager.Instance.RemoveCamera(uiCamera); } } ``` --- ## 四、开发流程 ### 4.1 需求分析 1. **明确需求**:理解业务需求,确定需要实现的功能 2. **评估复杂度**:判断是否需要核心库支持或扩展 3. **设计方案**:规划代码结构和调用关系 ### 4.2 代码编写 1. **创建目录**:在`GameBusiness`下创建对应模块目录 2. **编写代码**:遵循编码规范,使用核心库提供的API 3. **测试验证**:在Unity中测试功能正确性 ### 4.3 代码审查 1. **自我检查**:检查是否符合规范,是否有潜在问题 2. **团队审查**:提交代码进行团队审查 3. **修复问题**:根据审查意见修改代码 ### 4.4 集成测试 1. **模块测试**:测试单个模块功能 2. **集成测试**:测试模块间交互 3. **回归测试**:确保不影响现有功能 --- ## 五、最佳实践 ### 5.1 性能优化 #### 5.1.1 对象池使用 - 频繁创建销毁的对象必须使用对象池 - 合理设置对象池初始容量 - 定期清理空闲对象避免内存泄漏 #### 5.1.2 资源管理 - 及时释放不再使用的资源 - 使用异步加载避免卡顿 - 合理使用资源缓存 ### 5.2 代码组织 #### 5.2.1 单一职责 - 每个类只负责一个功能 - 避免庞大的God类 #### 5.2.2 依赖管理 - 通过管理器获取依赖,而非硬编码 - 使用接口解耦依赖关系 ### 5.3 错误处理 #### 5.3.1 异常捕获 - 在关键路径添加异常处理 - 记录错误日志便于排查 #### 5.3.2 防御性编程 - 检查参数合法性 - 处理空引用情况 --- ## 六、常见问题 ### 6.1 如何扩展核心库功能? 通过继承抽象类或实现接口来扩展,不要直接修改核心库代码。 ### 6.2 核心库有Bug怎么办? 提交Issue到框架团队,由框架团队修复并发布新版本。 ### 6.3 如何获取核心库的最新版本? 关注内部通知,定期更新核心库引用。 ### 6.4 如何调试核心库代码? 可以设置断点调试,但不允许修改代码。 --- ## 附录 ### A. 常用核心库API | 类别 | 管理器 | 常用方法 | |-----|-------|---------| | **对象池** | `HFObjectMemPool` | `GetItem()`, `GiveBack()` | | **事件** | `IHFEventHandle` | `AddListener()`, `Dispatch()` | | **资源** | `HFABMgr` | `OnStartLoad()` | | **相机** | `HFCameraManager` | `AddCamera()`, `GetCamera()` | ### B. 核心库只读目录 ``` Assets/StrayFog/Core/ Assets/Game/GameHFScripte/CopyToHF/ Assets/Game/GameGeneralScripte/ ``` --- **版本**: v1.0 **生效日期**: 2024年 **适用范围**: OnlineGame项目业务开发人员