Initial commit: UnityAI documentation and framework analysis
This commit is contained in:
377
StrayFog框架架构分析.md
Normal file
377
StrayFog框架架构分析.md
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
# StrayFog 框架架构分析
|
||||||
|
|
||||||
|
## 一、框架整体架构
|
||||||
|
|
||||||
|
### 1.1 模块划分
|
||||||
|
|
||||||
|
| 模块层级 | 路径 | 职责描述 |
|
||||||
|
|---------|------|---------|
|
||||||
|
| **Core层** | `Assets/StrayFog/Core` | 核心基础框架,模拟行为系统、全局数据管理 |
|
||||||
|
| **HF层** | `Assets/Game/GameHFScripte/CopyToHF` | 游戏核心业务框架,资源管理、事件系统、相机管理等 |
|
||||||
|
| **General层** | `Assets/Game/GameGeneralScripte` | 通用工具层,状态机、辅助工具等 |
|
||||||
|
|
||||||
|
### 1.2 架构图
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ StrayFog Framework │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ ┌──────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
|
||||||
|
│ │ GameGeneral │ │ GameHF │ │ Core │ │
|
||||||
|
│ │ 状态机/工具类 │ │ 业务核心模块 │ │ 基础框架层 │ │
|
||||||
|
│ └────────┬─────────┘ └────────┬─────────┘ └───────┬───────┘ │
|
||||||
|
├───────────┼─────────────────────┼───────────────────┼───────────┤
|
||||||
|
│ │ │ │ │
|
||||||
|
│ ▼ ▼ ▼ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Unity Engine │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、Core层架构
|
||||||
|
|
||||||
|
### 2.1 SimulateBehaviour 模拟行为系统
|
||||||
|
|
||||||
|
#### 2.1.1 核心接口
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public interface ISimulateBehaviour
|
||||||
|
{
|
||||||
|
long simulateGlobalId { get; } // 模拟行为全局ID
|
||||||
|
int bindGameObjectInstanceId { get; } // 绑定对象实例ID
|
||||||
|
void BindGameObject(GameObject _go); // 绑定GameObject
|
||||||
|
void UnBindGameObject(); // 解绑GameObject
|
||||||
|
// ... 完整的MonoBehaviour生命周期方法
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.2 设计目的
|
||||||
|
|
||||||
|
| 设计目标 | 实现方式 |
|
||||||
|
|---------|---------|
|
||||||
|
| **解耦MonoBehaviour** | 将逻辑从MonoBehaviour中剥离,便于测试和复用 |
|
||||||
|
| **生命周期控制** | 完整模拟Unity生命周期,支持自定义调度 |
|
||||||
|
| **对象池优化** | 配合对象池实现高效对象复用 |
|
||||||
|
|
||||||
|
#### 2.1.3 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
SimulateBehaviour/
|
||||||
|
├── ISimulateBehaviour.cs # 核心接口定义
|
||||||
|
├── Bind/ # 绑定实现
|
||||||
|
│ ├── IBindSimulateBehaviour.cs
|
||||||
|
│ ├── AbsBindSimulateBehaviour_Mono.cs # Mono绑定基类
|
||||||
|
│ ├── AbsBindSimulateBehaviour_UI.cs # UI绑定基类
|
||||||
|
│ └── BindSimulateBehaviour_Collect.cs # 收集器
|
||||||
|
├── MonoBehaviour/ # 各生命周期模拟实现
|
||||||
|
│ ├── SimulateMonoBehaviour_Awake__xxx.cs
|
||||||
|
│ ├── SimulateMonoBehaviour_Update__xxx.cs
|
||||||
|
│ └── ... (40+生命周期方法)
|
||||||
|
└── UIBehaviour/ # UI生命周期模拟
|
||||||
|
├── SimulateUIBehaviour_Awake__xxx.cs
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 全局数据管理
|
||||||
|
|
||||||
|
**SFGlobalData.cs** - 全局路径和平台管理
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class SFGlobalData
|
||||||
|
{
|
||||||
|
public static string assetBundleRoot; // AB包根路径
|
||||||
|
public static string streamingAssetsRoot; // 流式资源根路径
|
||||||
|
public static string cdnassetBundleRoot; // CDN资源路径
|
||||||
|
public static RuntimePlatform Platform(); // 当前平台判断
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、HF层架构
|
||||||
|
|
||||||
|
### 3.1 接口体系
|
||||||
|
|
||||||
|
#### 3.1.1 核心接口继承链
|
||||||
|
|
||||||
|
```
|
||||||
|
IHFObject (基础对象接口)
|
||||||
|
├── IHFRecycle (回收接口)
|
||||||
|
│ └── void Recycle();
|
||||||
|
├── IHFGlobal (全局对象接口)
|
||||||
|
│ └── long globalId { get; }
|
||||||
|
├── IHFClone (克隆接口)
|
||||||
|
├── IHFLanguage (语言接口)
|
||||||
|
├── IHFScene (场景接口)
|
||||||
|
└── IHFSerializable (序列化接口)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.1.2 接口职责表
|
||||||
|
|
||||||
|
| 接口 | 核心职责 | 关键字段/方法 |
|
||||||
|
|-----|---------|--------------|
|
||||||
|
| `IHFObject` | 基础对象标识 | 无 |
|
||||||
|
| `IHFRecycle` | 对象回收机制 | `Recycle()` |
|
||||||
|
| `IHFGlobal` | 全局唯一标识 | `globalId` |
|
||||||
|
| `IHFClone` | 对象克隆能力 | 系列Clone方法 |
|
||||||
|
| `IHFLanguage` | 多语言支持 | 语言切换 |
|
||||||
|
| `IHFScene` | 场景管理 | 场景加载/卸载 |
|
||||||
|
|
||||||
|
### 3.2 对象池系统
|
||||||
|
|
||||||
|
#### 3.2.1 HFObjectMemPool - GameObject对象池
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class HFObjectMemPool
|
||||||
|
{
|
||||||
|
private Queue<GameObject> m_UnoccupiedPool; // 空闲队列
|
||||||
|
private Dictionary<int, GameObject> m_UsingPool; // 使用中字典
|
||||||
|
public GameObject GetItem(out bool isnew); // 获取对象
|
||||||
|
public void GiveBack(GameObject item); // 归还对象
|
||||||
|
public void Recycle(); // 完全回收
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2.2 HFScriptMemPool<T> - 泛型脚本对象池
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class HFScriptMemPool<T> : IHFRecycle
|
||||||
|
where T : IHFRecycle
|
||||||
|
{
|
||||||
|
private Queue<T> m_UnoccupiedPool;
|
||||||
|
private List<T> m_UsingPool;
|
||||||
|
// 支持MonoBehaviour和普通类的自动创建
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2.3 对象池设计特点
|
||||||
|
|
||||||
|
| 特性 | 实现方式 | 优势 |
|
||||||
|
|-----|---------|-----|
|
||||||
|
| **双池结构** | 空闲池 + 使用池 | 高效管理对象状态 |
|
||||||
|
| **内存泄漏检测** | 归还时校验来源 | 及时发现问题 |
|
||||||
|
| **泛型支持** | `HFScriptMemPool<T>` | 类型安全 |
|
||||||
|
| **Mono支持** | 自动创建GameObject | 无缝集成Unity |
|
||||||
|
|
||||||
|
### 3.3 事件系统
|
||||||
|
|
||||||
|
#### 3.3.1 核心接口
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public interface IHFEventHandle<K,T> : IHFRecycle
|
||||||
|
{
|
||||||
|
void AddListener<T1>(K key, Action<T> callback); // 添加监听
|
||||||
|
void RemoveListener<T1>(K key, Action<T> action); // 移除监听
|
||||||
|
void Dispatch(T arg); // 分发事件
|
||||||
|
void RemoveAll(K key); // 清空监听
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.2 AbsHFEventHandle 实现机制
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public abstract class AbsHFEventHandle<K,T> : IHFEventHandle<K,T>
|
||||||
|
where K : struct, Enum
|
||||||
|
where T : IHFEventArg<K>
|
||||||
|
{
|
||||||
|
// 多级索引: EventId -> TypeHashCode -> Action列表
|
||||||
|
HFMultiKeyDictionary<K, int, IHFCacheEventAction<K,T>> mICacheEventActionMaping;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.3 事件系统架构
|
||||||
|
|
||||||
|
```
|
||||||
|
事件分发流程:
|
||||||
|
Dispatch(arg)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
获取 EventId 对应的 Action字典
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
获取 参数类型HashCode 对应的 CacheEventAction
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
遍历执行所有 Action<T>
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
调用 arg.Recycle() 回收事件参数
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 AssetBundle 资源管理器
|
||||||
|
|
||||||
|
#### 3.4.1 HFABMgr 核心结构
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public partial class HFABMgr : AbsHFSingleMonoBehaviour<HFABMgr>
|
||||||
|
{
|
||||||
|
public float progress { get; } // 加载进度
|
||||||
|
Dictionary<int, HFAssetLoader> mHFAssetLoaderMaping; // 加载器映射
|
||||||
|
Dictionary<int, HFAssetBundlePathAttribute> mHFAssetBundlePathAttributeMaping; // 属性映射
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.2 资源加载流程
|
||||||
|
|
||||||
|
```
|
||||||
|
资源加载流程:
|
||||||
|
OnStartLoad(request)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
检查缓存 → 获取/创建 HFAssetLoader
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
loader.AddRequest(request)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
loader.LoadAsset() → 异步加载
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
加载完成 → 回调处理
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.3 依赖管理
|
||||||
|
|
||||||
|
通过Manifest文件解析资源依赖关系:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
HFAssetBundlePathAttribute OnGetDependencyAbpAttr(string _depManifestName)
|
||||||
|
{
|
||||||
|
// 解析依赖项名称 → 获取属性 → 缓存
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 相机管理系统
|
||||||
|
|
||||||
|
#### 3.5.1 HFCameraManager 架构
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public partial class HFCameraManager : AbsHFSingleRunTime<HFCameraManager>
|
||||||
|
{
|
||||||
|
private Dictionary<int, AbsHFCameraItem> m_List_CameraItem; // 相机列表
|
||||||
|
public HFMainCamera mainCamera; // 主相机
|
||||||
|
|
||||||
|
public void AddCamera(AbsHFCameraItem cameraItem); // 添加相机
|
||||||
|
public void RemoveCamera(AbsHFCameraItem cameraItem); // 移除相机
|
||||||
|
public AbsHFEventHandle GetCamera(string _cameraName); // 获取相机
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.5.2 相机堆栈管理
|
||||||
|
|
||||||
|
```
|
||||||
|
相机层级架构:
|
||||||
|
HFMainCamera (主相机)
|
||||||
|
│
|
||||||
|
├── CameraStack (相机堆栈)
|
||||||
|
│ ├── CameraItem1 (Weight=10)
|
||||||
|
│ ├── CameraItem2 (Weight=20)
|
||||||
|
│ └── CameraItem3 (Weight=5)
|
||||||
|
│
|
||||||
|
└── 按Weight排序 → 渲染顺序控制
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、General层架构
|
||||||
|
|
||||||
|
### 4.1 状态机系统
|
||||||
|
|
||||||
|
#### 4.1.1 核心类层次
|
||||||
|
|
||||||
|
```
|
||||||
|
IGFStateMachineBehaviour (接口)
|
||||||
|
│
|
||||||
|
├── AbsGFStateMachineBehaviour (抽象基类)
|
||||||
|
│ ├── AbsGFAttachStateBehaviour (状态行为)
|
||||||
|
│ ├── AbsGFAttachLayerBehaviour (层行为)
|
||||||
|
│ └── AbsGFAttachMachineBehaviour (机行为)
|
||||||
|
│
|
||||||
|
└── IGFStateMachineBehaviourClassify (分类接口)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.1.2 状态机特性
|
||||||
|
|
||||||
|
| 特性 | 说明 |
|
||||||
|
|-----|-----|
|
||||||
|
| **层级化设计** | 支持状态、层、机三个层级的行为绑定 |
|
||||||
|
| **参数化驱动** | 通过参数控制状态切换 |
|
||||||
|
| **Inspector扩展** | 自定义编辑器支持 |
|
||||||
|
|
||||||
|
### 4.2 工具类
|
||||||
|
|
||||||
|
#### 4.2.1 扩展方法集合
|
||||||
|
|
||||||
|
**HFUGUIExtendEngine.cs** - UGUI扩展方法(40+方法)
|
||||||
|
|
||||||
|
| 功能分类 | 方法示例 |
|
||||||
|
|---------|---------|
|
||||||
|
| **坐标转换** | `HFWorldToLocalPointInRectangle` |
|
||||||
|
| **布局操作** | `HFFixedPositionInCanvas`, `HFForceRebuildLayoutImmediate` |
|
||||||
|
| **RectTransform** | `HFIdentityStreech`, `HFCopyRectTransformFrom` |
|
||||||
|
| **事件监听** | `HFAddListener` |
|
||||||
|
|
||||||
|
#### 4.2.2 其他工具
|
||||||
|
|
||||||
|
| 工具类 | 职责 |
|
||||||
|
|-------|-----|
|
||||||
|
| `HFAssetBundleHelper` | AB包辅助工具 |
|
||||||
|
| `HFDllHelper` | DLL加载辅助 |
|
||||||
|
| `HFEnumForAssetBundle` | AB包相关枚举 |
|
||||||
|
| `MinGameModel` | 微信小游戏适配 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、架构设计特点
|
||||||
|
|
||||||
|
### 5.1 设计模式应用
|
||||||
|
|
||||||
|
| 模式 | 应用场景 | 实现类 |
|
||||||
|
|-----|---------|-------|
|
||||||
|
| **单例模式** | 全局管理器 | `AbsHFSingleMonoBehaviour`, `AbsHFSingleRunTime` |
|
||||||
|
| **工厂模式** | 对象创建 | 对象池的GetItem |
|
||||||
|
| **观察者模式** | 事件系统 | `IHFEventHandle` |
|
||||||
|
| **策略模式** | 多平台适配 | `SFGlobalData.Platform()` |
|
||||||
|
| **模板方法** | 生命周期 | `SimulateBehaviour`系列 |
|
||||||
|
|
||||||
|
### 5.2 架构优势
|
||||||
|
|
||||||
|
| 优势 | 体现 |
|
||||||
|
|-----|-----|
|
||||||
|
| **解耦性** | 逻辑与MonoBehaviour分离 |
|
||||||
|
| **可测试性** | 纯逻辑类易于单元测试 |
|
||||||
|
| **性能优化** | 对象池减少GC |
|
||||||
|
| **扩展性** | 接口驱动,易于扩展 |
|
||||||
|
| **可维护性** | 清晰的模块划分 |
|
||||||
|
|
||||||
|
### 5.3 潜在改进点
|
||||||
|
|
||||||
|
| 改进方向 | 说明 |
|
||||||
|
|---------|-----|
|
||||||
|
| **异步加载优化** | 可引入协程池或Job System |
|
||||||
|
| **资源依赖可视化** | 可增加依赖关系图工具 |
|
||||||
|
| **性能监控** | 可增加加载时间、内存占用统计 |
|
||||||
|
| **热更新支持** | 可考虑集成Lua或ILRuntime |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、总结
|
||||||
|
|
||||||
|
StrayFog框架是一个结构清晰、设计完善的Unity游戏框架,核心特点包括:
|
||||||
|
|
||||||
|
1. **模拟行为系统** - 实现了完整的MonoBehaviour生命周期解耦
|
||||||
|
2. **对象池机制** - 高效的内存管理策略
|
||||||
|
3. **事件驱动架构** - 灵活的事件分发系统
|
||||||
|
4. **资源管理体系** - 完善的AssetBundle加载和依赖管理
|
||||||
|
5. **模块化设计** - 清晰的分层和职责划分
|
||||||
|
|
||||||
|
该框架适合中大型Unity项目使用,具备良好的扩展性和维护性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**版本**: v1.0
|
||||||
|
**分析日期**: 2024年
|
||||||
|
**适用项目**: OnlineGame
|
||||||
567
业务开发指南.md
Normal file
567
业务开发指南.md
Normal file
@@ -0,0 +1,567 @@
|
|||||||
|
# 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<BulletComponent>().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<GameEventArgs> m_ArgPool;
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
m_ArgPool = new HFScriptMemPool<GameEventArgs>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GameEventId>, 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
|
||||||
|
/// <summary>
|
||||||
|
/// 卡组窗口
|
||||||
|
/// </summary>
|
||||||
|
[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/CardDeck/CardDeckWindow.prefab")]
|
||||||
|
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Dynamic, isIgnoreCloseByESC = false)]
|
||||||
|
public class CardDeckWindow : AbsHFUIWindow
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化(仅调用一次)
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnRunAwake()
|
||||||
|
{
|
||||||
|
base.OnRunAwake();
|
||||||
|
// 初始化UI组件引用
|
||||||
|
// 绑定事件监听(如按钮点击等)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打开窗口(每次打开调用)
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnOpen(Action _onOpenComplete)
|
||||||
|
{
|
||||||
|
base.OnOpen(_onOpenComplete);
|
||||||
|
// 注册客户端内部消息监听(CTCEvent)
|
||||||
|
HFFunCatalogue.Event.CTCEvent.AddListener<HFEvent_CTC_CardUpdate>(enHFCTCEvent.CardUpdate, OnCardUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭窗口
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnClose(Action _onCloseComplete)
|
||||||
|
{
|
||||||
|
base.OnClose(_onCloseComplete);
|
||||||
|
// 取消客户端内部消息监听
|
||||||
|
HFFunCatalogue.Event.CTCEvent.RemoveListener<HFEvent_CTC_CardUpdate>(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<PlayerManager>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 注册模拟Behaviour事件
|
||||||
|
/// 通过此属性声明需要监听的事件
|
||||||
|
/// </summary>
|
||||||
|
protected override int[] simulateBehaviourEvents => new int[]
|
||||||
|
{
|
||||||
|
enHFSimulateBehaviourEvent.Mono_Update,
|
||||||
|
enHFSimulateBehaviourEvent.Mono_FixedUpdate
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单例创建时调用(仅一次)
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnAfterCreateInstance()
|
||||||
|
{
|
||||||
|
base.OnAfterCreateInstance();
|
||||||
|
// 初始化逻辑
|
||||||
|
RegisterServerEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模拟Update事件(通过simulateBehaviourEvents注册后自动调用)
|
||||||
|
/// 注:这是封装后的事件,非Unity原生MonoBehaviour.Update
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnRunUpdate()
|
||||||
|
{
|
||||||
|
// 每帧更新逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模拟FixedUpdate事件
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnRunFixedUpdate()
|
||||||
|
{
|
||||||
|
// 物理更新逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册服务器事件监听
|
||||||
|
/// </summary>
|
||||||
|
void RegisterServerEvents()
|
||||||
|
{
|
||||||
|
HFFunCatalogue.Event.STCEvent.AddListener<HFEvent_STC_PlayerInfo>(enHFSTCEvent.PlayerInfo, OnPlayerInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPlayerInfo(HFEventArgBase arg)
|
||||||
|
{
|
||||||
|
HFEvent_STC_PlayerInfo info = arg as HFEvent_STC_PlayerInfo;
|
||||||
|
// 处理服务器返回的玩家信息
|
||||||
|
// 触发客户端事件通知UI更新
|
||||||
|
HFEvent_CTC_PlayerLevelUp evt = HFFunCatalogue.New<HFEvent_CTC_PlayerLevelUp>();
|
||||||
|
evt.playerId = info.playerId;
|
||||||
|
evt.newLevel = info.level;
|
||||||
|
HFFunCatalogue.Event.CTCEvent.Dispatch(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例2:使用AbsHFSingleRunTime(纯逻辑)**
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ConfigManager : AbsHFSingleRunTime<ConfigManager>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 单例创建时调用(仅一次)
|
||||||
|
/// </summary>
|
||||||
|
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<GameObject> onLoaded)
|
||||||
|
{
|
||||||
|
// 通过HFFunCatalogue统一入口加载资源
|
||||||
|
// resId: 从Res配置表中读取的资源ID
|
||||||
|
HFFunCatalogue.Asset.LoadAsset(resId, (res, obj) =>
|
||||||
|
{
|
||||||
|
if (obj != null)
|
||||||
|
{
|
||||||
|
GameObject model = res.GetAsset<GameObject>();
|
||||||
|
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<GameObject>();
|
||||||
|
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<UIOverlayCamera>();
|
||||||
|
cameraMgr.AddCamera(uiCamera);
|
||||||
|
|
||||||
|
// 获取主相机
|
||||||
|
Camera mainCam = cameraMgr.mainCamera.MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
UIOverlayCamera uiCamera = GetComponent<UIOverlayCamera>();
|
||||||
|
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项目业务开发人员
|
||||||
80
核心库保护规范.md
Normal file
80
核心库保护规范.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# StrayFog 框架核心库保护规范
|
||||||
|
|
||||||
|
## 一、核心库定义
|
||||||
|
|
||||||
|
### 1.1 核心库范围(只读)
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `Assets/StrayFog/Core` | 基础框架核心 |
|
||||||
|
| `Assets/Game/GameHFScripte/CopyToHF` | 游戏核心业务框架 |
|
||||||
|
| `Assets/Game/GameGeneralScripte` | 通用工具层 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、保护规则
|
||||||
|
|
||||||
|
### 2.1 访问方式
|
||||||
|
|
||||||
|
**业务代码必须通过 `HFFunCatalogue` 统一入口访问核心库:**
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ✅ 正确:通过统一入口访问
|
||||||
|
HFFunCatalogue.UIManager.OpenWindow<LoginWindow>();
|
||||||
|
HFFunCatalogue.Asset.LoadAsset<GameObject>("path");
|
||||||
|
HFFunCatalogue.Scene.LoadScene("MainScene");
|
||||||
|
|
||||||
|
// ❌ 禁止:直接访问核心库
|
||||||
|
HFUIWindowMgr.Instance.OpenWindow<LoginWindow>(); // 禁止
|
||||||
|
HFABMgr.Instance.LoadAsset<GameObject>("path"); // 禁止
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 禁止操作
|
||||||
|
|
||||||
|
| 禁止行为 | 后果 |
|
||||||
|
|---------|------|
|
||||||
|
| 修改核心库源代码 | 破坏框架稳定性 |
|
||||||
|
| 删除/重命名核心库文件 | 编译错误 |
|
||||||
|
| 直接实例化核心库内部类 | 违反封装原则 |
|
||||||
|
| 绕过 `HFFunCatalogue` 直接调用核心库单例 | 难以维护和测试 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、修改流程
|
||||||
|
|
||||||
|
```
|
||||||
|
业务人员发现问题/需求
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
提交Issue到框架团队
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
框架团队评估需求
|
||||||
|
│
|
||||||
|
┌────┴────┐
|
||||||
|
│ │
|
||||||
|
合理 不合理
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
开发修复 反馈拒绝
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
代码审查 → 发布新版本 → 业务团队更新引用
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、违规处理
|
||||||
|
|
||||||
|
| 等级 | 违规行为 | 处理方式 |
|
||||||
|
|-----|---------|---------|
|
||||||
|
| **轻微** | 误修改注释、空行 | 警告+恢复 |
|
||||||
|
| **一般** | 修改非核心逻辑 | 通报批评+代码回滚 |
|
||||||
|
| **严重** | 修改核心逻辑导致Bug | 绩效扣分+修复责任 |
|
||||||
|
| **重大** | 删除核心文件导致崩溃 | 追责+修复责任 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**版本**: v1.0
|
||||||
|
**生效日期**: 2024年
|
||||||
|
**适用范围**: OnlineGame项目
|
||||||
Reference in New Issue
Block a user