Skip to content

WasiCore 框架概述 ​

本文用于查阅框架分工。有地图编辑器或 Unity / Urho 经验的读者,可先读理解星火迁移已有知识;零基础用户可直接从快速开始做出第一个可玩目标。具体功能按需组合现成玩法系统和引擎能力,不要求整个项目只采用一种方式。

架构设计 ​

WasiCore 采用分层架构设计,各层职责明确,通过接口进行通信。

系统架构图 ​

┌─────────────────────────────────────────────────────────┐
│                     应用层 (Game Entry)                  │
├─────────────────────────────────────────────────────────┤
│                      UI层 (GameUI)                       │
├─────────────────────────────────────────────────────────┤
│                   游戏逻辑层 (GameCore)                  │
├──────────────────────────┬──────────────────────────────┤
│     数据层 (GameData)     │  场景图引擎封装 (GameGraph)   │
├──────────────────────────┴──────────────────────────────┤
│               引擎层 (Engine Interface / Urho3D)         │
├─────────────────────────────────────────────────────────┤
│                   平台层 (Platform)                      │
└─────────────────────────────────────────────────────────┘

> GameGraph 是连接 GameCore 游戏逻辑与底层 Urho3D 引擎的桥梁,提供节点、物理、资源、材质等能力。Unit、Actor、Scene 可以通过类型明确的入口访问底层节点与组件。表现节点、单位绑定节点和场景根有不同用途,unit.GetNode() 的双端语义也不同;实际写法与控制归属见 GameCore 与 GameGraph 桥接,能力清单见 GameGraph 总览。

网络架构 ​

┌──────────────┐         ┌──────────────┐
│   客户端     │◄────────►│   服务器     │
│  (Client)    │         │  (Server)    │
├──────────────┤         ├──────────────┤
│ GameUI       │         │ Game Logic   │
│ Rendering    │         │ Simulation   │
│ Input        │         │ Authority    │
├──────────────┤         ├──────────────┤
│ Protocol     │         │ Protocol     │
│ Client       │         │ Server       │
└──────────────┘         └──────────────┘
      ▲                          ▲
      └──────── Network ─────────┘
           (MessagePack)

游戏体系选型指南 ​

WasiCore 框架包含两套可独立或组合使用的体系。选择正确的体系是游戏架构决策的第一步。

> 如果用户只说“2D 游戏”或“3D 游戏”,不要直接按视觉维度选择路线。先读 游戏架构路线、SCE 场景空间模型与 Canvas/GameGraph 边界:区分 SCE Unit/技能系统、直接 GameGraph SceneGraph、Canvas/GameUI 绘制路线,再判断 SCE 场景使用 Surface2D 还是 Volumetric3D。

体系一:核心游戏逻辑体系(GameCore + GameData) ​

提供的能力:Entity/Unit/Ability/Buff/Item/Effect/Order/AI/Trigger/GameData/Player/DualEndEvent

设计目标:服务器权威、数据驱动、自动同步的单位制联机游戏。这条路线可以承载 3D 画面、2.5D 单层地表或真 3D 多层空间;空间语义由 GameDataScene.SpaceModel 决定,而不是由画面风格决定。

适合的游戏类型:

  • MOBA / RTS / 塔防 — Unit + Ability + AI + Order
  • RPG / ARPG — Unit + Ability + Buff + Item + Quest
  • 回合制策略 — Entity + GameData + Trigger
  • 需要联机对战、排行榜、云存档的任何游戏

核心优势:

  • 服务端创建 Entity/Unit → 自动同步到所有客户端
  • 内置技能/Buff/物品/冷却/属性系统,无需从零编写
  • 触发器系统支持图形化编辑器(无需写代码即可编排逻辑)
  • 双端事件 / TypedMessage / ProtoCustomMessage 三级通信机制

体系二:场景图引擎封装(GameGraph) ​

提供的能力:Node/SceneGraph/Component/Physics/Physics2D/Material/Resource/ScriptComponent

设计目标:通用的 3D/2D 场景图与物理引擎封装,底层对接 Urho3D。用户可以直接用 SceneGraph / Node 构造 3D 游戏或工具预览,而不经过 SCE Unit/技能系统;代价是不会自动获得 Unit、Ability、Buff、AI、目标过滤等高层玩法框架。

适合的游戏类型:

  • 物理解谜 / 弹球 / 弹珠台 — Physics2D + ScriptComponent
  • 平台跳跃 / 横版动作 — Physics2D + ScriptComponent
  • 3D 场景展示 / 沙盒搭建 — Node + StaticMesh + Light + Material
  • 赛车 / 自由物理模拟 — RigidBody + CollisionShape

> 关键边界:GameGraph 已双端化,但子系统运行端不同。 > > | 模块 | 客户端专属 | 双端可用 | > |------|:----------😐:--------😐 > | Graphics(Light, Zone, Skybox, Camera, StaticMesh, PrimitiveShape, Drawable) | 全部 | — | > | MaterialSystem(Material, MaterialPBR, MaterialFlatLambert 等) | 全部 | — | > | Physics2D(RigidBody2D, PhysicsWorld2D, 所有 Collision/Constraint 2D 组件) | — | 全部 | > | ResourceSystem | MeshBuilder | Mesh, Texture2D, Shader, Prefab | > | NodeSystem 核心 | — | Node, SceneGraph, 发布/复制模式 | > | Physics 3D | — | RigidBody, PhysicsWorld, CollisionShape | > | Scripts | — | ScriptComponent | > > 客户端本地创建的 GameGraph 仍只是本地表现层,不会自动获得联机同步、服务器权威逻辑或持久化。需要同步脚本创建的 GameGraph 场景时,应在服务端创建 replicated SceneGraph 并按玩家 Publish(player);多数完整联机游戏仍建议以核心体系为主体,再组合 GameGraph。

两套体系的组合方式 ​

大多数成熟的游戏会同时使用两套体系,让它们各司其职:

服务端                                客户端
┌────────────────────┐              ┌────────────────────────────────┐
│  GameCore 核心体系  │  ──同步──▶  │  GameCore 核心体系              │
│  • Unit 创建/销毁   │              │  • Unit 状态同步接收            │
│  • Ability 施放判定 │              │  • 事件驱动 Actor 表现          │
│  • 属性计算         │              │                                │
│  • AI 决策          │              │  GameGraph 场景图/表现层         │
│  • 碰撞判定(2D/3D)   │              │  • Light/Zone/Skybox 场景搭建  │
│                    │              │  • Material 材质控制            │
│  GameGraph          │              │  • Physics2D 本地表现/映射       │
│  • Node/SceneGraph  │              │  • ScriptComponent 帧逻辑      │
│  • 2D/3D物理/发布图   │              │  • StaticMesh/PrimitiveShape   │
└────────────────────┘              └────────────────────────────────┘

典型组合模式:

模式服务端用客户端用适合
纯核心体系Entity/Unit/Ability/TriggerActor 视觉表现 + UI传统 MOBA/RTS/RPG(通常是 Surface2D 单层地表,但画面仍可 3D 渲染)
核心 + GameGraph 渲染增强同上核心体系 + Light/Zone/Skybox/Material 搭建 3D 场景需要精细 3D 画面的联机游戏;不等于必须使用 Volumetric3D
核心 + GameGraph 物理增强Unit/Ability 管理游戏逻辑;必要时服务端 Physics2D/3D 做权威模拟接收 replicated Node,或用 Physics2D 做本地表现/预测联机游戏中需要额外 2D/3D 物理对象或物理表现
服务端 GameGraph 发布图SceneGraph + 2D/3D Physics + Publish(player)接收 replicated SceneGraph / Node 事件非 Unit 的服务端权威 2D/3D 物件、机关、调试对象
纯客户端 GameGraph不使用全部用本地 GameGraph单机物理游戏/原型验证

桥接方式:

csharp
using GameGraph.NodeSystem;

// scene 是已经加载完成的 SCE 场景。
var graph = scene.GetSceneGraph();
#if CLIENT
// 在保留 Unit 玩法的同时,查询已有表现组件。
var model = unit.GetAnimatedModel();
var controller = unit.GetAnimationController();
#endif

需要物理角色或自定义绑定节点时,先确定移动、同步与清理归属,再添加相应组件,详见桥接参考。

选型决策流程 ​

你的游戏需要联机/对战/服务器逻辑吗?
├── 是 → 默认以核心体系(GameCore)承载游戏规则和持久化
│        ├── 游戏类型是单位制(有角色/技能/属性)?
│        │   ├── 是 → Unit + Ability + Buff(核心体系主力)
│        │   └── 否 → Entity + GameData + 自定义逻辑
│        └── 需要同步非 Unit 的 3D 场景物件吗?
│            ├── 是 → 服务端 GameGraph 发布图(高级路径)
│            └── 否 → 只在客户端组合 GameGraph 表现或 Actor 系统
└── 否(纯单机/原型)→ 可以纯用 GameGraph
         └── 但未来要加联机?→ 建议一开始就引入核心体系

🎯 核心概念 ​

1. 游戏类自动注册 (IGameClass Auto-Registration) ​

WasiCore 框架提供了自动游戏类注册机制,简化了系统初始化过程。

🔧 IGameClass 接口 ​

csharp
/// <summary>
/// Register game classes that are used in the game setups.
/// </summary>
public interface IGameClass
{
    static abstract void OnRegisterGameClass();
}

自动注册机制 ​

实现方式:

  1. 代码生成器扫描:编译时自动扫描所有实现 IGameClass 的类
  2. 自动生成注册代码:生成 AssemblySetup.g.cs 文件
  3. 运行时自动调用:游戏启动时自动调用所有 OnRegisterGameClass() 方法

使用示例:

csharp
// 定义游戏类
public class MyGameSystem : IGameClass
{
    public static void OnRegisterGameClass()
    {
        // 系统初始化逻辑
        Game.OnGameDataInitialization += OnGameDataInitialization;
        Game.Logger.LogInformation("🎮 MyGameSystem initialized");
    }
    
    private static void OnGameDataInitialization()
    {
        // 游戏数据初始化
    }
}

生成的注册代码:

csharp
// 自动生成的 AssemblySetup.g.cs
public static class AssemblySetup
{
    public static void Setup()
    {
        // 自动注册所有 IGameClass
        GameCore.GameSystem.Game.OnRegisterGameClasses += 
            GameCore.GameSystem.Game.RegisterGameClass<MyGameSystem>;
    }
}

主要优势 ​

  • 零配置:无需手动注册,编译时自动处理
  • 类型安全:编译时检查,避免运行时错误
  • 依赖管理:支持程序集间的依赖关系自动处理
  • 统一初始化:所有系统在统一的生命周期中初始化

重要提示 ​

  • 无需手动调用:OnRegisterGameClass() 方法会被框架自动调用
  • 静态方法:必须是静态方法,因为在类实例化之前调用
  • 幂等性:确保多次调用的安全性(避免重复注册)
  • Game.GameModeLink 不可用:OnRegisterGameClass() 在 GameModeLink 赋值之前执行,此阶段不能用 Game.GameModeLink 判断游戏模式。游戏模式判断应放在 OnGameDataInitialization 或 OnGameTriggerInitialization 的 handler 中
  • 客户端 UI 时序:OnGameUIInitialization 早于 OnGameTriggerInitialization。如需初始化 UI,必须在 OnRegisterGameClass() 阶段提前订阅
  • 完整生命周期:完整启动顺序与阶段职责请见 guides/FrameworkLifecycle.md

2. 坐标系统 (Coordinate System) ​

WasiCore 框架采用特定的坐标系统约定,请务必区分2D场景和3D空间的不同约定。

重要区分:2D场景 vs 3D空间 ​

2D场景坐标系统(UI、地图俯视图):

场景坐标系统(2D俯视视角):

(0,0) ←─────────────────────► X轴正方向(右方)
  │
  │
  │
  │
  ▼
Y轴正方向(下方)

3D空间坐标系统(实际游戏世界):

3D空间坐标系统:

       ▲ Z轴正方向(上方,高度轴)
       │
       │
       │
(0,0,0)├─────────────► Y轴正方向(前后,深度)
      ╱
     ╱
    ▼
X轴正方向(左右,水平)

XY平面 = 地面

📐 关键约定说明 ​

2D场景约定(用于UI、小地图等):

  • 原点位置:场景 (0,0) 点位于地图的左上方
  • X轴正方向:指向右方
  • Y轴正方向:指向下方

3D空间约定(用于游戏世界、物理、形状等):

  • X轴正方向:水平方向(左右移动)
  • Y轴正方向:水平方向(前后移动,深度)
  • Z轴正方向:高度方向(上下移动,跳跃轴)
  • XY平面:地面水平面
  • Z轴:高度轴,Z=0为地面,Z>0为空中

坐标系手性说明 ​

WasiCore使用左手坐标系(Left-handed coordinate system),与Unreal Engine保持一致:

左手定则验证:
👍 拇指 → X轴正方向(右)
👆 食指 → Y轴正方向(前)  
🖕 中指 → Z轴正方向(上)

默认镜头设置:

  • Yaw: -90° (水平旋转)
  • Pitch: -70° (俯视角)
  • Roll: 0° (无倾斜)
  • 默认视角:俯视角2.5D镜头
  • 默认镜头下的原点位置:左上角

这种设计的优势:

  • 兼容性:与Unreal Engine的坐标系完全一致
  • 标准化:遵循主流3D引擎的左手坐标系约定
  • 简化开发:减少从其他引擎迁移的坐标转换复杂度

与其他引擎的差异 ​

引擎/系统原点位置Y轴正方向坐标系手性备注
WasiCore左上角前方左手坐标系与UE一致,默认俯视角,默认镜头Yaw有-90°的旋转,因此默认镜头下,原点位置在左上角
Unity中心或左下上方左手坐标系3D世界坐标系
Unreal Engine中心前方左手坐标系与WasiCore一致
DirectX左下上方左手坐标系传统3D约定
OpenGL左下上方右手坐标系传统3D约定
Web/UI左上下方2D坐标系仅2D平面

实际应用场景 ​

这种坐标系统约定会影响以下开发场景:

1. 2D场景使用(地图、UI):

csharp
// 地图左上角(2D场景)
var topLeft = new ScenePoint(0, 0, scene);

// 向右移动100单位(2D场景)
var moveRight = new ScenePoint(100, 0, scene);

// 向下移动100单位(2D场景)
var moveDown = new ScenePoint(0, 100, scene);

2. 3D空间使用(游戏世界):

csharp
// 地面位置(3D空间)
var groundPosition = new ScenePoint(new Vector3(100, 200, 0), scene);

// 跳跃中的角色(3D空间)
var jumpingPlayer = new ScenePoint(new Vector3(100, 200, 50), scene);

// 飞行物体(3D空间)
var flyingObject = new ScenePoint(new Vector3(100, 200, 150), scene);

3. 物理和移动(3D空间):

csharp
// 水平移动:X或Y增加
unit.MoveTo(new ScenePoint(new Vector3(newX, newY, currentZ), scene));

// 垂直移动(跳跃):Z增加
unit.MoveTo(new ScenePoint(new Vector3(currentX, currentY, newZ), scene));

// 重力下落:Z减少
velocity.Z -= gravity * deltaTime;

开发建议 ​

针对 AI 助手的关键提醒:

  1. 3D游戏开发:始终使用Z轴作为高度轴(跳跃、重力、飞行)
  2. 2D界面开发:使用传统的XY坐标系(Y向下)
  3. 物理系统:重力作用在Z轴负方向,跳跃在Z轴正方向
  4. 形状创建:Vector3(x, y, z)中,XY为地面位置,Z为高度
  5. 碰撞检测:地面接触检查Z坐标,水平距离检查XY坐标

2D方向常量(UI、地图):

csharp
public static class Direction2D
{
    public static readonly Vector2 Up = new(0, -1);      // Y减少(2D向上)
    public static readonly Vector2 Down = new(0, 1);     // Y增加(2D向下)
    public static readonly Vector2 Left = new(-1, 0);    // X减少
    public static readonly Vector2 Right = new(1, 0);    // X增加
}

3D方向参考值(游戏世界):

方向Vector3说明
前(0, 1, 0)Y 正方向
后(0, -1, 0)Y 负方向
左(-1, 0, 0)X 负方向
右(1, 0, 0)X 正方向
上(0, 0, 1)Z 正方向(跳跃)
下(0, 0, -1)Z 负方向(重力)

> 框架不提供 Direction3D 静态类,需要在项目中自行定义方向常量。详细信息请参考 坐标系统指南。

3. 实体系统 (Entity System) ​

实体系统是游戏对象的基础,专门处理游戏逻辑、状态管理和网络同步。

csharp
// 实体层次结构(游戏逻辑)
Entity
├── Unit       // 单位(玩家、NPC)
├── Building   // 建筑
├── Item       // 物品
├── Effect     // 逻辑效果
└── Projectile // 投射物

关键特性:

  • 组件化设计:实体通过组件组合功能
  • 生命周期管理:自动处理创建、更新、销毁
  • 网络同步:内置网络同步机制
  • 服务端权威:所有实体必须在服务端创建

4. 表现系统 (Actor System) ​

表现系统专注于游戏世界的视觉表现,与实体系统形成明确的职责分离。

csharp
// 表现层次结构(视觉表现)
Actor
├── ActorModel     // 模型表现
├── ActorParticle  // 粒子表现
├── ActorSound     // 声音表现
├── ActorText      // 文本表现
├── ActorBeam      // 光束表现
└── ActorSegmented // 分段表现

关键特性:

  • 轻量级创建:客户端可直接创建
  • 视觉专注:专门处理模型、特效、声音
  • 灵活生命周期:支持瞬态和持久化
  • 附着系统:支持复杂的视觉层次结构

5. 架构分离原则 ​

游戏对象架构 - 职责分离:

Entity 家族(游戏逻辑)          Actor 家族(视觉表现)
┌─────────────────────┐        ┌─────────────────────┐
│ • 服务端权威        │        │ • 客户端创建        │
│ • 状态同步          │        │ • 视觉效果          │
│ • 游戏逻辑          │        │ • 轻量级            │
│ • 属性管理          │        │ • 瞬态/持久         │
└─────────────────────┘        └─────────────────────┘
         │                              │
         └─────── 可以协作 ─────────────┘

设计原则:

  • Entity 负责 "逻辑的" - 状态、属性、行为、同步
  • Actor 负责 "看到的" - 模型、特效、动画、声音
  • 两者可以协作但职责明确分离

6. 技能系统 (Ability System) ​

技能系统提供了灵活的技能定义和执行框架。

核心组件:

  • Ability:技能定义
  • Effect:技能效果
  • Modifier:属性修改器
  • Cooldown:冷却管理
  • Cost:消耗管理

执行流程:

  1. 检查施法条件(冷却、消耗、目标)
  2. 支付消耗
  3. 执行效果链
  4. 应用修改器
  5. 触发事件

7. UI系统 (UI System) ​

基于控件树的UI系统,支持数据绑定和事件路由。

控件层次:

UIRoot
├── Control
│   ├── Panel
│   ├── Button
│   ├── Label
│   └── ...
└── Layout
    ├── StackPanel
    ├── Grid
    └── Canvas

特性:

  • 属性系统:丰富的控件属性
  • 事件路由:冒泡和隧道事件
  • 数据绑定:MVVM模式支持
  • 布局系统:灵活的布局管理

UI模板数据结构 vs 运行时属性 ​

⚠️ 重要区别:UI系统中的属性访问方式在模板定义和运行时控件中有所不同。

在UI模板 (GameData) 中:

csharp
// 布局属性位于 Layout 对象下
_ = new GameDataControlButton(Control.TestButton)
{
    Layout = new()  // 布局属性在 Layout 对象中
    {
        Width = 500,
        Height = 90,
        HorizontalAlignment = HorizontalAlignment.Center,
        VerticalAlignment = VerticalAlignment.Center,
    },
    Event = new()   // 事件位于 Event 对象下
    {
        OnPointerClicked = (s, e) => { /* 处理点击 */ }
    }
};

在运行时控件类中:

csharp
// 属性直接作为控件的属性
var button = new Button
{
    Width = 500,                    // 直接属性
    Height = 90,                    // 直接属性
    HorizontalAlignment = HorizontalAlignment.Center,  // 直接属性
    VerticalAlignment = VerticalAlignment.Center       // 直接属性
};

// 事件直接订阅
button.OnPointerClicked += (s, e) => { /* 处理点击 */ };  // 直接事件

关键差异总结:

  • 模板定义:Layout.Width、Event.OnPointerClicked
  • 运行时控件:Width、OnPointerClicked(直接属性/事件)

这种设计允许模板系统更好地组织和管理复杂的UI数据结构,同时为运行时提供简洁直观的API。

8. 事件系统 (Event System) ​

基于发布-订阅模式的事件系统,支持同步和异步事件。

csharp
// 事件流程
EventSource → EventBus → EventHandler
     ↓            ↓            ↓
  发布者      事件总线      订阅者

事件类型:

  • 游戏事件:游戏逻辑相关
  • UI事件:用户交互
  • 网络事件:网络状态变化
  • 系统事件:系统级别事件

9. 数据系统 (Data System) ​

统一的游戏数据管理系统,支持热重载和版本控制。

数据类型:

  • 静态数据:配置表、常量
  • 动态数据:运行时数据
  • 持久化数据:存档数据

WebAssembly 运行环境限制 ​

WasiCore 编译为 WebAssembly 运行,有以下关键限制:

  • 无线程池:Task.Run() 和 TaskCreationOptions.RunContinuationsAsynchronously 禁用,直接 await 异步方法;TaskCompletionSource 使用默认构造函数
  • 无 Task.Delay:使用 Game.Delay() 替代
  • 无 Console:使用 Game.Logger.LogInformation() 参数化模板
  • JSON 序列化不支持多维数组:需要网络传输(服务端/客户端通信)的数据不能使用 [,],改用一维数组

相关文档 ​