6026 lines
188 KiB
Markdown
6026 lines
188 KiB
Markdown
# XCEngine - 仿Unity引擎架构设计文档
|
||
|
||
> **⚠️ 重要声明(严禁修改!)**
|
||
> 下文出现矛盾时永远以开头声明为准!!!!!!!!
|
||
> 本架构**1:1参考传统Unity引擎架构**(GameObject + MonoBehaviour模式),**不是Unity DOTS**!
|
||
>
|
||
> - 组件是**类**(引用类型),包含数据和行为
|
||
> - 实体是GameObject容器
|
||
> - 系统是OOP风格的类
|
||
> - 不是纯数据组件 + 纯函数系统的DOTS模式
|
||
> - 不是SoA内存布局(**除粒子系统性能关键路径外**)
|
||
> - 不要被"ECS"这个词误导,这里是传统Unity的Component模式
|
||
> - TransformComponent继承自Component,与Unity的GetComponent\<Transform\>() API行为一致
|
||
|
||
---
|
||
|
||
## 文档信息
|
||
|
||
- **版本**: 1.0
|
||
- **日期**: 2026-03-12
|
||
- **状态**: 架构设计文档
|
||
- **目标**: 构建类Unity的专业游戏引擎
|
||
|
||
---
|
||
|
||
## 第一章 整体架构概览
|
||
|
||
### 1.1 架构设计原则
|
||
|
||
本引擎采用**分层架构**结合**模块化设计**,遵循以下核心原则:
|
||
|
||
1. **关注点分离 (Separation of Concerns)**: 各系统独立演化,通过明确定义的接口通信
|
||
2. **依赖倒置 (Dependency Inversion)**: 上层模块依赖抽象接口,不依赖具体实现
|
||
3. **开闭原则 (Open-Closed)**: 对扩展开放,对修改封闭
|
||
4. **单一职责 (Single Responsibility)**: 每个模块只负责一项职责
|
||
5. **数据驱动 (Data-Driven)**: 引擎行为由数据(组件、资源、配置)驱动
|
||
6. **组件化架构**: 采用类Unity的组件模式,组件挂载在实体上
|
||
7. **渲染抽象**: 跨 API 的渲染接口,便于多平台支持
|
||
|
||
### 1.2 整体架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ XCGameEngine │
|
||
├─────────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐│
|
||
│ │ Editor │ │ Runtime │ │ Toolchain ││
|
||
│ │ (编辑器) │ │ (运行时) │ │ (工具链) ││
|
||
│ ├─────────────────┤ ├─────────────────┤ ├─────────────────────────┤│
|
||
│ │ • UI Framework │ │ • Game Loop │ │ • Asset Processor ││
|
||
│ │ • Scene View │ │ • Component Update │ │ • Shader Compiler ││
|
||
│ │ • Inspector │ │ • Physics Sim │ │ • Mesh Optimizer ││
|
||
│ │ • Hierarchy │ │ • Audio Engine │ │ • Texture Compressor ││
|
||
│ │ • Project │ │ • Script VM │ │ • Build Pipeline ││
|
||
│ │ • Console │ │ • Networking │ │ • Profiler ││
|
||
│ └────────┬────────┘ └────────┬────────┘ └────────────┬────────────┘│
|
||
│ │ │ │ │
|
||
│ └───────────────────────┼──────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Engine Core │ │
|
||
│ ├────────────────────────────────────────────────────────────────────────┤ │
|
||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │
|
||
│ │ │ Renderer │ │ Scene │ │ Resource │ │ Components ││ │
|
||
│ │ │ (渲染) │ │ (场景) │ │ (资源) │ │ (组件系统) ││ │
|
||
│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │
|
||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │
|
||
│ │ │ Physics │ │ Audio │ │ Script │ │ Math ││ │
|
||
│ │ │ (物理) │ │ (音频) │ │ (脚本) │ │ (数学) ││ │
|
||
│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │
|
||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │
|
||
│ │ │ Memory │ │ Thread │ │ Network │ │ File ││ │
|
||
│ │ │ (内存) │ │ (线程) │ │ (网络) │ │ (文件) ││ │
|
||
│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Platform Layer │ │
|
||
│ ├────────────────────────────────────────────────────────────────────────┤ │
|
||
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │
|
||
│ │ │ D3D12 │ │ Vulkan │ │ Metal │ │ OpenGL │ │ │
|
||
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 1.3 目录结构设计
|
||
|
||
```
|
||
XCVolumeRenderer/
|
||
├── engine/ # 引擎核心库(静态库)
|
||
│ ├── CMakeLists.txt
|
||
│ ├── include/
|
||
│ │ └── XCGameEngine/
|
||
│ │ ├── Core/ # 核心基础
|
||
│ │ │ ├── Assert.h
|
||
│ │ │ ├── Enum.h
|
||
│ │ │ ├── Flags.h
|
||
│ │ │ ├── TypeTraits.h
|
||
│ │ │ ├── Variant.h
|
||
│ │ │ └── UniquePtr.h
|
||
│ │ ├── Math/ # 数学库
|
||
│ │ │ ├── Vector2.h
|
||
│ │ │ ├── Vector3.h
|
||
│ │ │ ├── Vector4.h
|
||
│ │ │ ├── Matrix2.h
|
||
│ │ │ ├── Matrix3.h
|
||
│ │ │ ├── Matrix4.h
|
||
│ │ │ ├── Quaternion.h
|
||
│ │ │ ├── Transform.h
|
||
│ │ │ ├── Color.h
|
||
│ │ │ ├── MathUtils.h
|
||
│ │ │ ├── Ray.h
|
||
│ │ │ ├── Plane.h
|
||
│ │ │ ├── Sphere.h
|
||
│ │ │ ├── Box.h
|
||
│ │ │ └── Frustum.h
|
||
│ │ ├── Containers/ # 容器
|
||
│ │ │ ├── Array.h
|
||
│ │ │ ├── FixedArray.h
|
||
│ │ │ ├── Vector.h
|
||
│ │ │ ├── Map.h
|
||
│ │ │ ├── Set.h
|
||
│ │ │ ├── HashMap.h
|
||
│ │ │ ├── String.h
|
||
│ │ │ └── RingBuffer.h
|
||
│ │ ├── Memory/ # 内存管理
|
||
│ │ │ ├── Allocator.h
|
||
│ │ │ ├── StackAllocator.h
|
||
│ │ │ ├── PoolAllocator.h
|
||
│ │ │ ├── FreeListAllocator.h
|
||
│ │ │ ├── ProxyAllocator.h
|
||
│ │ │ └── MemoryUtils.h
|
||
│ │ ├── Threading/ # 线程
|
||
│ │ │ ├── Thread.h
|
||
│ │ │ ├── Mutex.h
|
||
│ │ │ ├── RWLock.h
|
||
│ │ │ ├── Semaphore.h
|
||
│ │ │ ├── ThreadPool.h
|
||
│ │ │ ├── TaskSystem.h
|
||
│ │ │ ├── SpinLock.h
|
||
│ │ │ └── Atomic.h
|
||
│ │ ├── IO/ # 文件IO
|
||
│ │ │ ├── FileSystem.h
|
||
│ │ │ ├── Path.h
|
||
│ │ │ ├── Stream.h
|
||
│ │ │ ├── FileReader.h
|
||
│ │ │ ├── FileWriter.h
|
||
│ │ │ ├── Archive.h
|
||
│ │ │ └── Compression.h
|
||
│ │ ├── Debug/ # 调试
|
||
│ │ │ ├── Logger.h
|
||
│ │ │ ├── Profiler.h
|
||
│ │ │ ├── DebugDraw.h
|
||
│ │ │ ├── Assertion.h
|
||
│ │ │ └── Traces.h
|
||
│ │ ├── Components/ # 组件系统(类Unity GameObject模式)
|
||
│ │ │ ├── GameObject.h # 游戏对象
|
||
│ │ │ ├── Component.h # 组件基类
|
||
│ │ │ └── System.h # 系统基类
|
||
│ │ ├── Scene/ # 场景系统
|
||
│ │ │ ├── Scene.h
|
||
│ │ │ ├── SceneLoader.h
|
||
│ │ │ ├── SceneSerializer.h
|
||
│ │ │ ├── SubScene.h
|
||
│ │ │ └── SceneManager.h
|
||
│ │ ├── Renderer/ # 渲染系统
|
||
│ │ │ ├── ForwardDeclarations.h
|
||
│ │ │ ├── Device.h
|
||
│ │ │ ├── Context.h
|
||
│ │ │ ├── SwapChain.h
|
||
│ │ │ ├── Buffer.h
|
||
│ │ │ ├── Texture.h
|
||
│ │ │ ├── Shader.h
|
||
│ │ │ ├── Pipeline.h
|
||
│ │ │ ├── RenderPass.h
|
||
│ │ │ ├── RenderTarget.h
|
||
│ │ │ ├── CommandList.h
|
||
│ │ │ ├── CommandQueue.h
|
||
│ │ │ ├── Descriptor.h
|
||
│ │ │ ├── Fence.h
|
||
│ │ │ ├── QueryHeap.h
|
||
│ │ │ ├── GpuResource.h
|
||
│ │ │ ├── GpuAllocator.h
|
||
│ │ │ ├── GpuEvent.h
|
||
│ │ │ ├── RenderModule.h
|
||
│ │ │ ├── RenderGraph.h
|
||
│ │ │ ├── Light.h
|
||
│ │ │ ├── Camera.h
|
||
│ │ │ ├── Material.h
|
||
│ │ │ ├── Mesh.h
|
||
│ │ │ ├── Skybox.h
|
||
│ │ │ ├── DebugRenderer.h
|
||
│ │ │ └── PostProcess.h
|
||
│ │ ├── Resources/ # 资源系统
|
||
│ │ │ ├── Resource.h
|
||
│ │ │ ├── ResourceManager.h
|
||
│ │ │ ├── ResourceLoader.h
|
||
│ │ │ ├── ResourceCache.h
|
||
│ │ │ ├── AssetDatabase.h
|
||
│ │ │ ├── ImportSettings.h
|
||
│ │ │ ├── ResourceCooker.h
|
||
│ │ │ └── Bundle.h
|
||
│ │ ├── Physics/ # 物理系统
|
||
│ │ │ ├── PhysicsWorld.h
|
||
│ │ │ ├── RigidBody.h
|
||
│ │ │ ├── Collider.h
|
||
│ │ │ ├── Joint.h
|
||
│ │ │ ├── CharacterController.h
|
||
│ │ │ ├── Trigger.h
|
||
│ │ │ ├── Raycast.h
|
||
│ │ │ ├── ForceField.h
|
||
│ │ │ └── PhysicsMaterial.h
|
||
│ │ ├── Audio/ # 音频系统
|
||
│ │ │ ├── AudioEngine.h
|
||
│ │ │ ├── AudioSource.h
|
||
│ │ │ ├── AudioListener.h
|
||
│ │ │ ├── AudioClip.h
|
||
│ │ │ ├── AudioMixer.h
|
||
│ │ │ ├── AudioEffect.h
|
||
│ │ │ └── AudioBanks.h
|
||
│ │ ├── Scripting/ # 脚本系统
|
||
│ │ │ ├── ScriptEngine.h
|
||
│ │ │ ├── ScriptClass.h
|
||
│ │ │ ├── ScriptObject.h
|
||
│ │ │ ├── ScriptMethod.h
|
||
│ │ │ ├── MonoBridge.h
|
||
│ │ │ ├── LuaBridge.h
|
||
│ │ │ └── AngelScript.h
|
||
│ │ ├── Animation/ # 动画系统
|
||
│ │ │ ├── Animator.h
|
||
│ │ │ ├── AnimationClip.h
|
||
│ │ │ ├── AnimationCurve.h
|
||
│ │ │ ├── AnimationState.h
|
||
│ │ │ ├── AnimationBlendTree.h
|
||
│ │ │ ├── Skeleton.h
|
||
│ │ │ ├── Bone.h
|
||
│ │ │ ├── Skinning.h
|
||
│ │ │ └── BlendShape.h
|
||
│ │ ├── Particles/ # 粒子系统
|
||
│ │ │ ├── ParticleSystem.h
|
||
│ │ │ ├── ParticleEmitter.h
|
||
│ │ │ ├── ParticleRenderer.h
|
||
│ │ │ ├── ParticleForce.h
|
||
│ │ │ ├── GPUParticles.h
|
||
│ │ │ └── VFXGraph.h
|
||
│ │ ├── Networking/ # 网络系统
|
||
│ │ │ ├── NetworkManager.h
|
||
│ │ │ ├── NetworkClient.h
|
||
│ │ │ ├── NetworkServer.h
|
||
│ │ │ ├── NetworkPeer.h
|
||
│ │ │ ├── Packet.h
|
||
│ │ │ ├── Serializer.h
|
||
│ │ │ ├── RPC.h
|
||
│ │ │ ├── NetworkTransform.h
|
||
│ │ │ └── NetcodeProtocol.h
|
||
│ │ ├── UI/ # UI系统
|
||
│ │ │ ├── Canvas.h
|
||
│ │ │ ├── Element.h
|
||
│ │ │ ├── Image.h
|
||
│ │ │ ├── Text.h
|
||
│ │ │ ├── Button.h
|
||
│ │ │ ├── ScrollView.h
|
||
│ │ │ ├── LayoutGroup.h
|
||
│ │ │ ├── UIRenderer.h
|
||
│ │ │ └── Font.h
|
||
│ │ ├── Navigation/ # 导航系统
|
||
│ │ │ ├── NavMesh.h
|
||
│ │ │ ├── NavMeshAgent.h
|
||
│ │ │ ├── NavMeshQuery.h
|
||
│ │ │ ├── Obstacle.h
|
||
│ │ │ └── CrowdSystem.h
|
||
│ │ ├── Platforms/ # 平台层
|
||
│ │ │ ├── Platform.h
|
||
│ │ │ ├── Windows.h
|
||
│ │ │ ├── Linux.h
|
||
│ │ │ ├── MacOS.h
|
||
│ │ │ ├── Android.h
|
||
│ │ │ ├── IOS.h
|
||
│ │ │ └── Web.h
|
||
│ │ └── XCGameEngine.h # 主头文件
|
||
│ ├── src/
|
||
│ │ ├── Core/
|
||
│ │ ├── Math/
|
||
│ │ ├── Components/ # 组件系统
|
||
│ │ ├── Scene/
|
||
│ │ ├── Renderer/
|
||
│ │ ├── Resources/
|
||
│ │ ├── Physics/
|
||
│ │ ├── Audio/
|
||
│ │ ├── Scripting/
|
||
│ │ └── ...
|
||
│ └── third_party/ # 第三方库
|
||
│ ├── stb/
|
||
│ ├── json/
|
||
│ ├── lua/
|
||
│ ├── physx/
|
||
│ └── etc.
|
||
│
|
||
├── editor/ # 编辑器项目(你的UI)
|
||
│ ├── CMakeLists.txt
|
||
│ ├── src/
|
||
│ │ ├── Application.h/cpp
|
||
│ │ ├── main.cpp
|
||
│ │ ├── Theme.h/cpp
|
||
│ │ ├── Core/
|
||
│ │ │ ├── Event.h
|
||
│ │ │ ├── AssetItem.h
|
||
│ │ │ └── LogEntry.h
|
||
│ │ ├── Managers/
|
||
│ │ │ ├── SelectionManager.h
|
||
│ │ │ ├── LogSystem.h/cpp
|
||
│ │ │ ├── ProjectManager.h/cpp
|
||
│ │ │ └── EditorSceneManager.h/cpp
|
||
│ │ ├── Panels/
|
||
│ │ │ ├── Panel.h/cpp
|
||
│ │ │ ├── MenuBar.h/cpp
|
||
│ │ │ ├── HierarchyPanel.h/cpp
|
||
│ │ │ ├── InspectorPanel.h/cpp
|
||
│ │ │ ├── SceneViewPanel.h/cpp
|
||
│ │ │ ├── GameViewPanel.h/cpp
|
||
│ │ │ ├── ProjectPanel.h/cpp
|
||
│ │ │ ├── ConsolePanel.h/cpp
|
||
│ │ │ ├── AssetsBrowserPanel.h/cpp
|
||
│ │ │ ├── AnimationPanel.h/cpp
|
||
│ │ │ ├── ProfilerPanel.h/cpp
|
||
│ │ │ └── SettingsPanel.h/cpp
|
||
│ │ ├── Windows/
|
||
│ │ │ ├── AssetImporter.h/cpp
|
||
│ │ │ ├── SceneHierarchyWindow.h/cpp
|
||
│ │ │ ├── ShaderEditor.h/cpp
|
||
│ │ │ ├── MaterialEditor.h/cpp
|
||
│ │ │ ├── AnimationEditor.h/cpp
|
||
│ │ │ └── PreferenceWindow.h/cpp
|
||
│ │ ├── Tools/
|
||
│ │ │ ├── Gizmo.h/cpp
|
||
│ │ │ ├── SelectionTool.h/cpp
|
||
│ │ │ ├── MoveTool.h/cpp
|
||
│ │ │ ├── RotateTool.h/cpp
|
||
│ │ │ ├── ScaleTool.h/cpp
|
||
│ │ │ └── EditorCamera.h/cpp
|
||
│ │ ├── Editor/
|
||
│ │ │ ├── EditorEngineLink.h/cpp
|
||
│ │ │ ├── EditorRenderView.h/cpp
|
||
│ │ │ ├── EditorModes.h
|
||
│ │ │ └── UndoRedo.h/cpp
|
||
│ │ └── ImGui/
|
||
│ │ ├── ImGuiRenderer.h/cpp
|
||
│ │ ├── ImGuiTheme.h/cpp
|
||
│ │ └── ImGuiWidgets.h/cpp
|
||
│ └── assets/
|
||
│ ├── fonts/
|
||
│ ├── icons/
|
||
│ └── themes/
|
||
│
|
||
├── runtime/ # 游戏运行时(独立可执行文件)
|
||
│ ├── CMakeLists.txt
|
||
│ ├── src/
|
||
│ │ ├── GameMain.cpp
|
||
│ │ ├── RuntimeConfig.h
|
||
│ │ └── EntryPoint.cpp
|
||
│ └── resources/
|
||
│ └── (烘焙后的场景和资源)
|
||
│
|
||
├── tools/ # 工具链
|
||
│ ├── AssetProcessor/ # 资源处理器
|
||
│ ├── ShaderCompiler/ # 着色器编译器
|
||
│ ├── SceneCooker/ # 场景烘焙工具
|
||
│ ├── TextureConverter/ # 纹理转换工具
|
||
│ ├── MeshOptimizer/ # 网格优化工具
|
||
│ ├── AudioImporter/ # 音频导入工具
|
||
│ ├── BuildTool/ # 构建打包工具
|
||
│ └── ShaderDebugger/ # 着色器调试工具
|
||
│
|
||
├── content/ # 资源内容
|
||
│ ├── Assets/
|
||
│ │ ├── Scenes/
|
||
│ │ ├── Materials/
|
||
│ │ ├── Meshes/
|
||
│ │ ├── Textures/
|
||
│ │ ├── Audio/
|
||
│ │ ├── Scripts/
|
||
│ │ ├── Shaders/
|
||
│ │ ├── Animations/
|
||
│ │ ├── Prefabs/
|
||
│ │ └── UI/
|
||
│ ├── Packages/ # 包管理
|
||
│ └── Library/ # 引擎库缓存
|
||
│ ├── ShaderLibrary/
|
||
│ ├── ShaderCache/
|
||
│ ├── AssetDatabase/
|
||
│ ├── SourceAssets/
|
||
│ └── ImportCache/
|
||
│
|
||
└── docs/ # 文档
|
||
├── Architecture.md
|
||
├── ComponentReference.md
|
||
├── ShaderGuide.md
|
||
└── APIReference.md
|
||
```
|
||
|
||
---
|
||
|
||
## 第二章 核心层 (Core Layer)
|
||
|
||
核心层提供引擎所有其他部分依赖的基础功能,是整个引擎的基石。
|
||
|
||
### 2.1 数学库 (Math Library)
|
||
|
||
#### 2.1.1 设计目标
|
||
|
||
- **高性能**: SIMD 优化,支持 SSE/AVX/NEON
|
||
- **精确性**: 满足游戏精度需求,避免浮点误差
|
||
- **完整性**: 覆盖游戏开发所需的所有数学类型
|
||
- **可读性**: 简洁清晰的 API 设计
|
||
|
||
#### 2.1.2 核心类型
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Math {
|
||
|
||
// 向量类型
|
||
struct Vector2 { float x, y; };
|
||
struct Vector3 { float x, y, z; };
|
||
struct Vector4 { float x, y, z, w; };
|
||
|
||
// 矩阵类型
|
||
struct Matrix3x3; // 3D变换
|
||
struct Matrix4x4; // 4D变换
|
||
struct Matrix2x2; // 2D变换
|
||
|
||
// 四元数 - 避免欧拉角万向节锁
|
||
struct Quaternion {
|
||
float x, y, z, w;
|
||
|
||
// 旋转变换
|
||
static Quaternion FromAxisAngle(const Vector3& axis, float radians);
|
||
static Quaternion FromEulerAngles(float pitch, float yaw, float roll);
|
||
static Quaternion FromRotationMatrix(const Matrix4x4& matrix);
|
||
static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t);
|
||
|
||
Vector3 ToEulerAngles() const;
|
||
Matrix4x4 ToMatrix4x4() const;
|
||
Vector3 operator*(const Vector3& v) const; // 旋转向量
|
||
};
|
||
|
||
// 变换 - 组合位置、旋转、缩放
|
||
struct Transform {
|
||
Vector3 position = Vector3::Zero();
|
||
Quaternion rotation = Quaternion::Identity();
|
||
Vector3 scale = Vector3::One();
|
||
|
||
Matrix4x4 ToMatrix() const;
|
||
Transform Inverse() const;
|
||
Transform operator*(const Transform& other) const; // 组合变换
|
||
Vector3 TransformPoint(const Vector3& point) const;
|
||
Vector3 TransformDirection(const Vector3& direction) const;
|
||
};
|
||
|
||
// 空间参照
|
||
enum class Space {
|
||
Self, // 自身局部空间
|
||
World // 世界空间
|
||
};
|
||
|
||
// 颜色
|
||
struct Color { float r, g, b, a; };
|
||
struct LinearColor; // 线性空间颜色
|
||
struct HDRColor; // HDR颜色
|
||
|
||
// 射线 - 用于射线检测和选择
|
||
struct Ray {
|
||
Vector3 origin;
|
||
Vector3 direction;
|
||
|
||
Vector3 GetPoint(float t) const;
|
||
bool Intersects(const Sphere& sphere, float& t) const;
|
||
bool Intersects(const Box& box, float& t) const;
|
||
bool Intersects(const Plane& plane, float& t) const;
|
||
};
|
||
|
||
// 包围体
|
||
struct Sphere { Vector3 center; float radius; };
|
||
struct Box { Vector3 center; Vector3 extents; Matrix4x4 transform; };
|
||
struct Frustum; // 视锥体
|
||
struct OBB; // 定向包围盒
|
||
struct AABB; // 轴对齐包围盒
|
||
|
||
} // namespace Math
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
#### 2.1.3 SIMD 优化示例
|
||
|
||
```cpp
|
||
// 使用 SIMD 进行向量运算
|
||
struct alignas(16) Vector3_SIMD {
|
||
union {
|
||
__m128 simd;
|
||
struct { float x, y, z, w; };
|
||
};
|
||
|
||
Vector3_SIMD operator+(const Vector3_SIMD& other) const {
|
||
Vector3_SIMD result;
|
||
result.simd = _mm_add_ps(simd, other.simd);
|
||
return result;
|
||
}
|
||
|
||
float Dot(const Vector3_SIMD& other) const {
|
||
__m128 dot = _mm_mul_ps(simd, other.simd);
|
||
__m128 temp = _mm_movehl_ps(dot, dot);
|
||
dot = _mm_add_ss(dot, temp);
|
||
return _mm_cvtss_f32(dot);
|
||
}
|
||
|
||
Vector3_SIMD Cross(const Vector3_SIMD& other) const {
|
||
Vector3_SIMD result;
|
||
__m128 a = _mm_shuffle_ps(simd, simd, _MM_SHUFFLE(3,0,2,1));
|
||
__m128 b = _mm_shuffle_ps(other.simd, other.simd, _MM_SHUFFLE(3,1,0,2));
|
||
result.simd = _mm_sub_ps(_mm_mul_ps(simd, a), _mm_mul_ps(other.simd, b));
|
||
result.simd = _mm_shuffle_ps(result.simd, result.simd, _MM_SHUFFLE(3,0,2,1));
|
||
return result;
|
||
}
|
||
};
|
||
```
|
||
|
||
### 2.2 内存管理 (Memory Management)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Memory {
|
||
|
||
// 分配器基类
|
||
class IAllocator {
|
||
public:
|
||
virtual ~IAllocator() = default;
|
||
|
||
virtual void* Allocate(size_t size, size_t alignment = 0) = 0;
|
||
virtual void Free(void* ptr) = 0;
|
||
virtual void* Reallocate(void* ptr, size_t newSize) = 0;
|
||
|
||
virtual size_t GetTotalAllocated() const = 0;
|
||
virtual size_t GetTotalFreed() const = 0;
|
||
virtual size_t GetPeakAllocated() const = 0;
|
||
virtual size_t GetAllocationCount() const = 0;
|
||
|
||
virtual const char* GetName() const = 0;
|
||
};
|
||
|
||
// 线性分配器 - 快速分配和批量释放
|
||
class LinearAllocator : public IAllocator {
|
||
public:
|
||
explicit LinearAllocator(size_t size, IAllocator* parent = nullptr);
|
||
~LinearAllocator();
|
||
|
||
void* Allocate(size_t size, size_t alignment = 8) override;
|
||
void Free(void* ptr) override; // 只重置,不真正释放
|
||
void Clear(); // 清空所有内存
|
||
|
||
void* GetMarker() const;
|
||
void SetMarker(void* marker);
|
||
|
||
private:
|
||
byte* m_buffer = nullptr;
|
||
size_t m_capacity = 0;
|
||
size_t m_offset = 0;
|
||
IAllocator* m_parent = nullptr;
|
||
};
|
||
|
||
// 池分配器 - 高频小对象分配
|
||
class PoolAllocator : public IAllocator {
|
||
public:
|
||
PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8);
|
||
~PoolAllocator();
|
||
|
||
void* Allocate(size_t size, size_t alignment = 0) override;
|
||
void Free(void* ptr) override;
|
||
|
||
bool Contains(void* ptr) const;
|
||
size_t GetBlockSize() const { return m_blockSize; }
|
||
size_t GetFreeBlockCount() const;
|
||
|
||
private:
|
||
struct FreeNode {
|
||
FreeNode* next;
|
||
};
|
||
|
||
size_t m_blockSize = 0;
|
||
size_t m_alignment = 0;
|
||
void* m_memory = nullptr;
|
||
FreeNode* m_freeList = nullptr;
|
||
size_t m_totalBlocks = 0;
|
||
size_t m_freeBlocks = 0;
|
||
};
|
||
|
||
// 代理分配器 - 用于追踪和调试
|
||
class ProxyAllocator : public IAllocator {
|
||
public:
|
||
ProxyAllocator(IAllocator* underlying, const char* name);
|
||
|
||
void* Allocate(size_t size, size_t alignment = 0) override;
|
||
void Free(void* ptr) override;
|
||
void* Reallocate(void* ptr, size_t newSize) override;
|
||
|
||
struct Stats {
|
||
size_t totalAllocated;
|
||
size_t totalFreed;
|
||
size_t peakAllocated;
|
||
size_t allocationCount;
|
||
size_t memoryOverhead;
|
||
};
|
||
const Stats& GetStats() const;
|
||
|
||
private:
|
||
IAllocator* m_underlying;
|
||
const char* m_name;
|
||
Stats m_stats;
|
||
Mutex m_mutex;
|
||
};
|
||
|
||
// 全局内存管理器
|
||
class MemoryManager {
|
||
public:
|
||
static MemoryManager& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
IAllocator* GetSystemAllocator();
|
||
IAllocator* GetPhysicsAllocator();
|
||
IAllocator* GetRenderingAllocator();
|
||
IAllocator* GetAudioAllocator();
|
||
|
||
std::unique_ptr<LinearAllocator> CreateLinearAllocator(size_t size);
|
||
std::unique_ptr<PoolAllocator> CreatePoolAllocator(size_t blockSize, size_t count);
|
||
std::unique_ptr<ProxyAllocator> CreateProxyAllocator(const char* name);
|
||
|
||
void SetTrackAllocations(bool track);
|
||
void DumpMemoryLeaks();
|
||
void GenerateMemoryReport();
|
||
};
|
||
|
||
#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__)
|
||
#define XE_FREE(allocator, ptr) allocator->Free(ptr)
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.3 线程系统 (Threading)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Threading {
|
||
|
||
enum class TaskPriority : uint8_t {
|
||
Critical = 0,
|
||
High = 1,
|
||
Normal = 2,
|
||
Low = 3,
|
||
Idle = 4
|
||
};
|
||
|
||
enum class TaskStatus : uint8_t {
|
||
Pending,
|
||
Scheduled,
|
||
Running,
|
||
Completed,
|
||
Failed,
|
||
Canceled
|
||
};
|
||
|
||
template<typename T = void()>
|
||
using Func = std::function<T>;
|
||
|
||
// 任务接口
|
||
class ITask {
|
||
public:
|
||
virtual ~ITask() = default;
|
||
|
||
virtual void Execute() = 0;
|
||
virtual void OnComplete() {}
|
||
virtual void OnCancel() {}
|
||
|
||
TaskPriority GetPriority() const { return m_priority; }
|
||
TaskStatus GetStatus() const { return m_status; }
|
||
uint64 GetId() const { return m_id; }
|
||
|
||
protected:
|
||
TaskPriority m_priority = TaskPriority::Normal;
|
||
TaskStatus m_status = TaskStatus::Pending;
|
||
uint64 m_id = 0;
|
||
std::atomic<uint32> m_refCount{1};
|
||
};
|
||
|
||
// Lambda 任务包装器
|
||
template<typename Func>
|
||
class LambdaTask : public ITask {
|
||
public:
|
||
explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal)
|
||
: m_func(std::move(func)), m_priority(priority) {}
|
||
|
||
void Execute() override {
|
||
m_func();
|
||
}
|
||
|
||
private:
|
||
Func m_func;
|
||
};
|
||
|
||
// 任务组 - 用于批量管理任务
|
||
class TaskGroup {
|
||
public:
|
||
using Callback = std::function<void()>;
|
||
|
||
TaskGroup();
|
||
~TaskGroup();
|
||
|
||
uint64 AddTask(std::unique_ptr<ITask> task);
|
||
uint64 AddTask(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
||
|
||
void AddDependency(uint64 taskId, uint64 dependsOn);
|
||
void Wait();
|
||
bool WaitFor(std::chrono::milliseconds timeout);
|
||
|
||
void SetCompleteCallback(Callback&& callback);
|
||
bool IsComplete() const;
|
||
float GetProgress() const;
|
||
};
|
||
|
||
// 任务系统主类
|
||
class TaskSystem {
|
||
public:
|
||
static TaskSystem& Get();
|
||
|
||
void Initialize(const TaskSystemConfig& config);
|
||
void Shutdown();
|
||
|
||
uint64 Submit(std::unique_ptr<ITask> task);
|
||
uint64 Submit(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
||
|
||
TaskGroup* CreateTaskGroup();
|
||
void DestroyTaskGroup(TaskGroup* group);
|
||
|
||
void Wait(uint64 taskId);
|
||
uint32 GetWorkerThreadCount() const;
|
||
|
||
void Update();
|
||
|
||
// 并行 For 循环
|
||
template<typename Func>
|
||
void ParallelFor(int32 start, int32 end, Func&& func);
|
||
|
||
void RunOnMainThread(Func&& func);
|
||
};
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.4 容器库 (Containers)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Containers {
|
||
|
||
// 动态数组
|
||
template<typename T>
|
||
class Array {
|
||
public:
|
||
using Iterator = T*;
|
||
using ConstIterator = const T*;
|
||
|
||
Array() = default;
|
||
explicit Array(size_t capacity);
|
||
Array(size_t count, const T& value);
|
||
Array(std::initializer_list<T> init);
|
||
~Array();
|
||
|
||
Array(const Array& other);
|
||
Array(Array&& other) noexcept;
|
||
Array& operator=(const Array& other);
|
||
Array& operator=(Array&& other) noexcept;
|
||
|
||
T& operator[](size_t index);
|
||
const T& operator[](size_t index) const;
|
||
|
||
T* Data() { return m_data; }
|
||
const T* Data() const { return m_data; }
|
||
|
||
size_t Size() const { return m_size; }
|
||
size_t Capacity() const { return m_capacity; }
|
||
|
||
void Clear();
|
||
void PushBack(const T& value);
|
||
void PushBack(T&& value);
|
||
template<typename... Args>
|
||
T& EmplaceBack(Args&&... args);
|
||
void PopBack();
|
||
|
||
private:
|
||
T* m_data = nullptr;
|
||
size_t m_size = 0;
|
||
size_t m_capacity = 0;
|
||
IAllocator* m_allocator = nullptr;
|
||
};
|
||
|
||
// 字符串
|
||
class String {
|
||
public:
|
||
String();
|
||
String(const char* str);
|
||
String(const char* str, size_t len);
|
||
~String();
|
||
|
||
String& operator+=(const String& other);
|
||
String& operator+=(const char* str);
|
||
|
||
String Substring(size_t pos, size_t len = npos) const;
|
||
String Trim() const;
|
||
String ToLower() const;
|
||
String ToUpper() const;
|
||
|
||
size_t Find(const char* str, size_t pos = 0) const;
|
||
bool StartsWith(const String& prefix) const;
|
||
bool EndsWith(const String& suffix) const;
|
||
|
||
const char* CStr() const { return m_data; }
|
||
size_t Length() const { return m_length; }
|
||
|
||
private:
|
||
char* m_data = nullptr;
|
||
size_t m_length = 0;
|
||
size_t m_capacity = 0;
|
||
};
|
||
|
||
// 哈希映射
|
||
template<typename Key, typename Value>
|
||
class HashMap {
|
||
public:
|
||
struct Pair {
|
||
Key first;
|
||
Value second;
|
||
};
|
||
|
||
HashMap() = default;
|
||
explicit HashMap(size_t bucketCount, IAllocator* allocator = nullptr);
|
||
|
||
Value& operator[](const Key& key);
|
||
Value* Find(const Key& key);
|
||
const Value* Find(const Key& key) const;
|
||
bool Contains(const Key& key) const;
|
||
|
||
bool Insert(const Key& key, const Value& value);
|
||
bool Erase(const Key& key);
|
||
void Clear();
|
||
|
||
size_t Size() const { return m_size; }
|
||
|
||
private:
|
||
size_t GetBucketIndex(const Key& key) const;
|
||
void Resize();
|
||
|
||
struct Bucket {
|
||
Array<Pair> pairs;
|
||
};
|
||
Array<Bucket> m_buckets;
|
||
size_t m_bucketCount = 0;
|
||
size_t m_size = 0;
|
||
float m_loadFactor = 0.75f;
|
||
IAllocator* m_allocator = nullptr;
|
||
};
|
||
|
||
} // namespace Containers
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 2.5 日志与调试系统
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Core {
|
||
|
||
// 事件系统 - 基础事件系统(线程安全版本)
|
||
template<typename... Args>
|
||
class Event {
|
||
public:
|
||
using Callback = std::function<void(Args...)>;
|
||
using Listener = std::pair<uint64_t, Callback>;
|
||
using Iterator = typename std::vector<Listener>::iterator;
|
||
|
||
uint64_t Subscribe(Callback callback) {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
uint64_t id = ++m_nextId;
|
||
m_listeners.emplace_back(id, std::move(callback));
|
||
return id;
|
||
}
|
||
|
||
void Unsubscribe(uint64_t id) {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
m_pendingUnsubscribes.push_back(id);
|
||
}
|
||
|
||
void ProcessUnsubscribes() {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
for (uint64_t id : m_pendingUnsubscribes) {
|
||
m_listeners.erase(
|
||
std::remove_if(m_listeners.begin(), m_listeners.end(),
|
||
[id](const auto& pair) { return pair.first == id; }),
|
||
m_listeners.end()
|
||
);
|
||
}
|
||
m_pendingUnsubscribes.clear();
|
||
}
|
||
|
||
void Invoke(Args... args) const {
|
||
// 注意:这里不加锁以避免回调中调用Unsubscribe导致的死锁
|
||
// 实际使用时应在调用前确保没有并发的Unsubscribe
|
||
// 或者使用副本进行调用
|
||
|
||
if (!m_pendingUnsubscribes.empty()) {
|
||
std::vector<Listener> listenersCopy;
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
listenersCopy = m_listeners;
|
||
m_pendingUnsubscribes.clear();
|
||
}
|
||
for (const auto& [id, callback] : listenersCopy) {
|
||
callback(args...);
|
||
}
|
||
} else {
|
||
for (const auto& [id, callback] : m_listeners) {
|
||
callback(args...);
|
||
}
|
||
}
|
||
}
|
||
|
||
void Clear() {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
m_listeners.clear();
|
||
}
|
||
|
||
Iterator begin() { return m_listeners.begin(); }
|
||
Iterator end() { return m_listeners.end(); }
|
||
|
||
private:
|
||
mutable std::mutex m_mutex;
|
||
std::vector<Listener> m_listeners;
|
||
std::vector<uint64_t> m_pendingUnsubscribes;
|
||
uint64_t m_nextId = 0;
|
||
};
|
||
|
||
// 基础类型定义
|
||
// 注意:String 定义在 Containers 命名空间中,避免与 Core::String 冲突
|
||
using int8 = int8_t;
|
||
using int16 = int16_t;
|
||
using int32 = int32_t;
|
||
using int64 = int64_t;
|
||
using uint8 = uint8_t;
|
||
using uint16 = uint16_t;
|
||
using uint32 = uint32_t;
|
||
using uint64 = uint64_t;
|
||
using byte = uint8_t;
|
||
|
||
// 引用计数基类
|
||
class RefCounted {
|
||
public:
|
||
RefCounted() : m_refCount(1) {}
|
||
virtual ~RefCounted() = default;
|
||
|
||
void AddRef() { ++m_refCount; }
|
||
void Release() {
|
||
if (--m_refCount == 0) {
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
uint32_t GetRefCount() const { return m_refCount.load(); }
|
||
|
||
protected:
|
||
std::atomic<uint32_t> m_refCount;
|
||
};
|
||
|
||
// 智能指针别名
|
||
template<typename T>
|
||
using Ref = std::shared_ptr<T>;
|
||
|
||
template<typename T>
|
||
using UniqueRef = std::unique_ptr<T>;
|
||
|
||
} // namespace Core
|
||
}
|
||
|
||
namespace XCEngine {
|
||
namespace Debug {
|
||
|
||
enum class LogLevel : uint8_t {
|
||
Verbose = 0,
|
||
Debug = 1,
|
||
Info = 2,
|
||
Warning = 3,
|
||
Error = 4,
|
||
Fatal = 5
|
||
};
|
||
|
||
enum class LogCategory {
|
||
General,
|
||
Rendering,
|
||
Physics,
|
||
Audio,
|
||
Scripting,
|
||
Network,
|
||
Memory,
|
||
Threading,
|
||
FileSystem,
|
||
Custom
|
||
};
|
||
|
||
struct LogEntry {
|
||
LogLevel level;
|
||
LogCategory category;
|
||
String message;
|
||
String file;
|
||
int32 line;
|
||
String function;
|
||
uint64 timestamp;
|
||
uint32 threadId;
|
||
};
|
||
|
||
class ILogSink {
|
||
public:
|
||
virtual ~ILogSink() = default;
|
||
virtual void Log(const LogEntry& entry) = 0;
|
||
virtual void Flush() = 0;
|
||
};
|
||
|
||
class ConsoleLogSink : public ILogSink {
|
||
public:
|
||
void Log(const LogEntry& entry) override;
|
||
void Flush() override;
|
||
void SetColorOutput(bool enable);
|
||
void SetMinimumLevel(LogLevel level);
|
||
};
|
||
|
||
class FileLogSink : public ILogSink {
|
||
public:
|
||
explicit FileLogSink(const String& filePath);
|
||
~FileLogSink();
|
||
void Log(const LogEntry& entry) override;
|
||
void Flush() override;
|
||
private:
|
||
String m_filePath;
|
||
FileWriter m_writer;
|
||
};
|
||
|
||
class Logger {
|
||
public:
|
||
static Logger& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void AddSink(std::unique_ptr<ILogSink> sink);
|
||
void RemoveSink(ILogSink* sink);
|
||
|
||
void Log(LogLevel level, LogCategory category,
|
||
const String& message, const char* file = nullptr,
|
||
int32 line = 0, const char* function = nullptr);
|
||
|
||
void Verbose(LogCategory category, const String& message);
|
||
void Debug(LogCategory category, const String& message);
|
||
void Info(LogCategory category, const String& message);
|
||
void Warning(LogCategory category, const String& message);
|
||
void Error(LogCategory category, const String& message);
|
||
void Fatal(LogCategory category, const String& message);
|
||
|
||
void SetMinimumLevel(LogLevel level);
|
||
void SetCategoryEnabled(LogCategory category, bool enabled);
|
||
};
|
||
|
||
#define XE_LOG(category, level, message) \
|
||
XCEngine::Debug::Logger::Get().Log(level, category, message, __FILE__, __LINE__, __FUNCTION__)
|
||
|
||
#define XE_ASSERT(condition, message) \
|
||
if (!(condition)) { \
|
||
XCEngine::Debug::Logger::Get().Fatal(XCEngine::Debug::LogCategory::General, message); \
|
||
__debugbreak(); \
|
||
}
|
||
|
||
// 性能分析器
|
||
class Profiler {
|
||
public:
|
||
static Profiler& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void BeginProfile(const char* name);
|
||
void EndProfile();
|
||
|
||
void BeginFrame();
|
||
void EndFrame();
|
||
|
||
void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId);
|
||
void SetMarker(const char* name, uint32_t color);
|
||
|
||
void ExportChromeTracing(const String& filePath);
|
||
};
|
||
|
||
#define XE_PROFILE_BEGIN(name) XCEngine::Debug::Profiler::Get().BeginProfile(name)
|
||
#define XE_PROFILE_END() XCEngine::Debug::Profiler::Get().EndProfile()
|
||
#define XE_PROFILE_FUNCTION() XE_PROFILE_BEGIN(__FUNCTION__)
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第三章 组件系统 (GameObject + Component)
|
||
|
||
> 本架构参考**传统Unity的GameObject + Component模式**。
|
||
> - GameObject是实体容器,包含Transform等内置组件
|
||
> - Component是挂载在GameObject上的class(引用类型),包含数据和行为
|
||
> - Component有完整的生命周期(Awake, Start, Update, OnDestroy等)
|
||
> - Scene直接管理GameObject列表,没有World中间层
|
||
|
||
### 3.1 组件系统架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ GameObject + Component Architecture │
|
||
├─────────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ Scene (场景) │ │
|
||
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ Scene │ │
|
||
│ │ │ ┌─────────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ │ GameObject List │ │ │
|
||
│ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │
|
||
│ │ │ │ │ GameObject │ │ GameObject │ │ GameObject │ │ │ │
|
||
│ │ │ │ │ - name │ │ - name │ │ - name │ │ │ │
|
||
│ │ │ │ │ - transform│ │ - transform│ │ - transform│ │ │ │
|
||
│ │ │ │ │ - components│ │ - components│ │ - components│ │ │ │
|
||
│ │ │ │ │ └ Renderer│ │ └ Camera │ │ └ Script │ │ │ │
|
||
│ │ │ │ └────────────┘ └────────────┘ └────────────┘ │ │ │
|
||
│ │ │ └─────────────────────────────────────────────────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 游戏对象 (GameObject)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class Scene;
|
||
class Transform;
|
||
class Component;
|
||
|
||
// GameObject: 游戏对象(类Unity GameObject)
|
||
// 传统Unity风格的GameObject,包含内置组件和用户组件
|
||
// 生命周期由 Scene 的 unique_ptr 管理,不需要引用计数
|
||
class GameObject {
|
||
public:
|
||
GameObject();
|
||
~GameObject();
|
||
|
||
// 内部构造 - 用于Scene创建GameObject时设置初始属性
|
||
struct ConstructParams {
|
||
String name = "GameObject";
|
||
GameObject* parent = nullptr;
|
||
bool active = true;
|
||
};
|
||
|
||
// 工厂方法(替代公有构造函数)
|
||
static GameObject* Create(const ConstructParams& params = {});
|
||
static void Destroy(GameObject* obj);
|
||
|
||
String name; // 对象名称
|
||
bool active = true; // 激活状态
|
||
|
||
TransformComponent& GetTransform() { return m_transform; }
|
||
const TransformComponent& GetTransform() const { return m_transform; }
|
||
|
||
Scene* GetScene() const { return m_scene; }
|
||
|
||
// 组件管理
|
||
template<typename T>
|
||
T* AddComponent();
|
||
|
||
template<typename T>
|
||
void RemoveComponent();
|
||
|
||
template<typename T>
|
||
T* GetComponent() const;
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponents() const;
|
||
|
||
template<typename T>
|
||
T* GetComponentInChildren() const;
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponentsInChildren() const;
|
||
|
||
template<typename T>
|
||
T* GetComponentInParent() const;
|
||
|
||
// 层级管理
|
||
GameObject* GetParent() const;
|
||
void SetParent(GameObject* parent);
|
||
void SetParent(GameObject* parent, bool worldPositionStays);
|
||
const std::vector<GameObject*>& GetChildren() const;
|
||
GameObject* GetChild(int index) const;
|
||
int GetChildCount() const;
|
||
int GetSiblingIndex() const;
|
||
void SetSiblingIndex(int index);
|
||
|
||
// 激活状态
|
||
void SetActive(bool active);
|
||
bool IsActive() const;
|
||
bool IsActiveInHierarchy() const;
|
||
|
||
// 场景查找(静态方法,内部使用SceneManager::GetActiveScene)
|
||
static GameObject* Find(const String& name);
|
||
static std::vector<GameObject*> FindObjectsOfType();
|
||
static std::vector<GameObject*> FindGameObjectsWithTag(const String& tag);
|
||
|
||
// 生命周期
|
||
void Destroy();
|
||
|
||
private:
|
||
void AddComponentInternal(Component* component);
|
||
void RemoveComponentInternal(Component* component);
|
||
|
||
std::vector<std::unique_ptr<Component>> m_components;
|
||
|
||
// 组件类型索引 - 用于O(1)查询(类型ID -> 组件索引)
|
||
// 每个 AddComponent/RemoveComponent 时更新
|
||
std::unordered_map<uint32_t, size_t> m_componentTypeIndex;
|
||
|
||
std::vector<GameObject*> m_children;
|
||
GameObject* m_parent = nullptr;
|
||
Scene* m_scene = nullptr;
|
||
|
||
// TransformComponent是GameObject的内置组件
|
||
// 注意:TransformComponent继承自Component,需要在构造后设置m_gameObject
|
||
TransformComponent m_transform;
|
||
|
||
void Initialize(const ConstructParams& params);
|
||
|
||
friend class Scene;
|
||
friend class TransformComponent;
|
||
};
|
||
|
||
// GameObject实现
|
||
inline GameObject::GameObject() {
|
||
// m_transform需要在构造后初始化m_gameObject
|
||
}
|
||
|
||
inline GameObject::~GameObject() {
|
||
// 销毁所有子对象
|
||
for (auto* child : m_children) {
|
||
delete child;
|
||
}
|
||
}
|
||
|
||
inline GameObject* GameObject::Create(const ConstructParams& params) {
|
||
GameObject* obj = new GameObject();
|
||
obj->Initialize(params);
|
||
return obj;
|
||
}
|
||
|
||
inline void GameObject::Destroy(GameObject* obj) {
|
||
delete obj;
|
||
}
|
||
|
||
inline void GameObject::Initialize(const ConstructParams& params) {
|
||
name = params.name;
|
||
active = params.active;
|
||
|
||
// 设置TransformComponent的m_gameObject指针
|
||
m_transform.m_gameObject = this;
|
||
|
||
// 设置父子关系
|
||
if (params.parent) {
|
||
params.parent->m_children.push_back(this);
|
||
m_parent = params.parent;
|
||
}
|
||
}
|
||
|
||
inline void GameObject::Destroy() {
|
||
if (m_scene) {
|
||
m_scene->DestroyGameObject(this);
|
||
} else {
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
// 静态方法实现
|
||
inline GameObject* GameObject::Find(const String& name) {
|
||
return SceneManager::Get().GetActiveScene()->Find(name);
|
||
}
|
||
|
||
inline std::vector<GameObject*> GameObject::FindObjectsOfType() {
|
||
return SceneManager::Get().GetActiveScene()->FindObjectsOfType<GameObject>();
|
||
}
|
||
|
||
inline std::vector<GameObject*> GameObject::FindGameObjectsWithTag(const String& tag) {
|
||
return SceneManager::Get().GetActiveScene()->FindGameObjectsWithTag(tag);
|
||
}
|
||
|
||
// GameObject创建辅助类
|
||
class GameObjectBuilder {
|
||
public:
|
||
explicit GameObjectBuilder(const String& name = "GameObject");
|
||
~GameObjectBuilder() = default;
|
||
|
||
template<typename T, typename... Args>
|
||
GameObjectBuilder& AddComponent(Args&&... args);
|
||
|
||
GameObject* Build();
|
||
|
||
private:
|
||
String m_name;
|
||
std::vector<std::function<void(GameObject*)>> m_components;
|
||
};
|
||
|
||
}
|
||
```
|
||
|
||
### 3.3 组件 (Component)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class GameObject;
|
||
|
||
// 组件基类(类Unity MonoBehaviour)
|
||
// 包含完整的生命周期方法,用户组件继承此类
|
||
// 注意:组件由GameObject拥有和管理生命周期,不需要引用计数
|
||
class Component {
|
||
public:
|
||
Component();
|
||
virtual ~Component();
|
||
|
||
// 所属GameObject
|
||
GameObject* gameObject() const { return m_gameObject; }
|
||
TransformComponent& transform() const { return m_gameObject->GetTransform(); }
|
||
|
||
// 激活状态
|
||
bool IsEnabled() const { return m_enabled; }
|
||
void SetEnabled(bool enabled) { m_enabled = enabled; }
|
||
|
||
// 场景引用
|
||
Scene* GetScene() const;
|
||
|
||
// 组件查找
|
||
template<typename T>
|
||
T* GetComponent() const { return m_gameObject->GetComponent<T>(); }
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponents() const { return m_gameObject->GetComponents<T>(); }
|
||
|
||
// ========================================
|
||
// 生命周期(类Unity MonoBehaviour)
|
||
// ========================================
|
||
|
||
// 创建时调用(即使组件被禁用也会调用)
|
||
virtual void Awake() {}
|
||
|
||
// 首次启用时调用(当对象和组件都被启用时)
|
||
virtual void Start() {}
|
||
|
||
// 每帧调用(当组件启用时)
|
||
virtual void Update(float deltaTime) {}
|
||
|
||
// 物理更新(固定时间间隔)
|
||
virtual void FixedUpdate() {}
|
||
|
||
// 在Update之后每帧调用
|
||
virtual void LateUpdate(float deltaTime) {}
|
||
|
||
// 销毁时调用
|
||
virtual void OnDestroy() {}
|
||
|
||
// 当组件被启用时调用
|
||
virtual void OnEnable() {}
|
||
|
||
// 当组件被禁用时调用
|
||
virtual void OnDisable() {}
|
||
|
||
// ========================================
|
||
// 物理回调(类Unity)
|
||
// ========================================
|
||
|
||
virtual void OnCollisionEnter(const Collision& collision) {}
|
||
virtual void OnCollisionStay(const Collision& collision) {}
|
||
virtual void OnCollisionExit(const Collision& collision) {}
|
||
|
||
virtual void OnTriggerEnter(Collider* other) {}
|
||
virtual void OnTriggerStay(Collider* other) {}
|
||
virtual void OnTriggerExit(Collider* other) {}
|
||
|
||
virtual void OnMouseDown() {}
|
||
virtual void OnMouseDrag() {}
|
||
virtual void OnMouseEnter() {}
|
||
virtual void OnMouseExit() {}
|
||
virtual void OnMouseOver() {}
|
||
virtual void OnMouseUp() {}
|
||
virtual void OnMouseUpAsButton() {}
|
||
|
||
virtual void OnTriggerEnter2D(Collider2D* other) {}
|
||
virtual void OnTriggerExit2D(Collider2D* other) {}
|
||
virtual void OnCollisionEnter2D(Collision2D* collision) {}
|
||
virtual void OnCollisionExit2D(Collision2D* collision) {}
|
||
|
||
// ========================================
|
||
// 消息发送
|
||
// ========================================
|
||
|
||
// 发送消息到同GameObject上的其他组件
|
||
void SendMessage(const String& methodName, const void* value = nullptr);
|
||
void SendMessageUpwards(const String& methodName, const void* value = nullptr);
|
||
void BroadcastMessage(const String& methodName, const void* value = nullptr);
|
||
|
||
protected:
|
||
GameObject* m_gameObject = nullptr;
|
||
bool m_enabled = true;
|
||
|
||
friend class GameObject;
|
||
};
|
||
|
||
// 组件类型注册(用于运行时类型识别)
|
||
class ComponentTypeRegistry {
|
||
public:
|
||
static ComponentTypeRegistry& Get();
|
||
|
||
template<typename T>
|
||
static uint32_t GetTypeId() {
|
||
static uint32_t id = Get().Register(typeid(T).name(), static_cast<uint32_t>(-1));
|
||
return id;
|
||
}
|
||
|
||
template<typename T>
|
||
static uint32_t GetTypeId(const char* typeName) {
|
||
static uint32_t id = Get().Register(typeName, static_cast<uint32_t>(-1));
|
||
return id;
|
||
}
|
||
|
||
static uint32_t GetTypeIdFromName(const char* typeName) {
|
||
return Get().GetIdByName(typeName);
|
||
}
|
||
|
||
static const char* GetTypeName(uint32_t typeId) {
|
||
return Get().GetNameById(typeId);
|
||
}
|
||
|
||
private:
|
||
uint32_t Register(const char* typeName, uint32_t suggestedId);
|
||
uint32_t GetIdByName(const char* typeName) const;
|
||
const char* GetNameById(uint32_t typeId) const;
|
||
|
||
std::atomic<uint32_t> m_nextTypeId{0};
|
||
std::unordered_map<uint32_t, String> m_idToName;
|
||
std::unordered_map<String, uint32_t> m_nameToId;
|
||
Mutex m_mutex;
|
||
};
|
||
|
||
// ============================================================================
|
||
// ============================================================================
|
||
// TransformComponent - GameObject的内置组件(类Unity Transform)
|
||
// 继承自 Component,包含父子层级关系
|
||
// ============================================================================
|
||
|
||
class TransformComponent : public Component {
|
||
public:
|
||
// 局部变换
|
||
Vector3 GetLocalPosition() const { return m_localPosition; }
|
||
void SetLocalPosition(const Vector3& position) { m_localPosition = position; SetDirty(); }
|
||
|
||
Quaternion GetLocalRotation() const { return m_localRotation; }
|
||
void SetLocalRotation(const Quaternion& rotation) { m_localRotation = rotation; SetDirty(); }
|
||
|
||
Vector3 GetLocalScale() const { return m_localScale; }
|
||
void SetLocalScale(const Vector3& scale) { m_localScale = scale; SetDirty(); }
|
||
|
||
// 世界变换(通过计算得出)
|
||
Vector3 GetPosition() const;
|
||
void SetPosition(const Vector3& position);
|
||
|
||
Quaternion GetRotation() const;
|
||
void SetRotation(const Quaternion& rotation);
|
||
|
||
Vector3 GetScale() const;
|
||
void SetScale(const Vector3& scale);
|
||
|
||
// 方向向量
|
||
Vector3 GetForward() const { return GetRotation() * Vector3::Forward(); }
|
||
Vector3 GetRight() const { return GetRotation() * Vector3::Right(); }
|
||
Vector3 GetUp() const { return GetRotation() * Vector3::Up(); }
|
||
|
||
// 矩阵
|
||
const Matrix4x4& GetLocalToWorldMatrix() const;
|
||
Matrix4x4 GetWorldToLocalMatrix() const;
|
||
|
||
// 层级操作
|
||
TransformComponent* GetParent() const { return m_parent; }
|
||
void SetParent(TransformComponent* parent, bool worldPositionStays = true);
|
||
|
||
int GetChildCount() const { return static_cast<int>(m_children.size()); }
|
||
TransformComponent* GetChild(int index) const;
|
||
TransformComponent* Find(const String& name) const;
|
||
|
||
void DetachChildren();
|
||
void SetAsFirstSibling();
|
||
void SetAsLastSibling();
|
||
void SetSiblingIndex(int index);
|
||
int GetSiblingIndex() const;
|
||
|
||
// 变换操作
|
||
void LookAt(const Vector3& target);
|
||
void LookAt(const Vector3& target, const Vector3& up);
|
||
void Rotate(const Vector3& eulers);
|
||
void Rotate(const Vector3& axis, float angle);
|
||
void Translate(const Vector3& translation);
|
||
void Translate(const Vector3& translation, Math::Space relativeTo);
|
||
|
||
// 点变换
|
||
Vector3 TransformPoint(const Vector3& point) const;
|
||
Vector3 InverseTransformPoint(const Vector3& point) const;
|
||
Vector3 TransformDirection(const Vector3& direction) const;
|
||
Vector3 InverseTransformDirection(const Vector3& direction) const;
|
||
|
||
// 设为脏(需要重新计算世界变换)
|
||
void SetDirty() { m_dirty = true; }
|
||
|
||
private:
|
||
Vector3 m_localPosition = Vector3::Zero();
|
||
Quaternion m_localRotation = Quaternion::Identity();
|
||
Vector3 m_localScale = Vector3::One();
|
||
|
||
TransformComponent* m_parent = nullptr;
|
||
std::vector<TransformComponent*> m_children;
|
||
|
||
mutable Matrix4x4 m_localToWorldMatrix;
|
||
mutable Matrix4x4 m_worldToLocalMatrix;
|
||
mutable Vector3 m_worldPosition;
|
||
mutable Quaternion m_worldRotation;
|
||
mutable Vector3 m_worldScale;
|
||
mutable bool m_dirty = true;
|
||
|
||
void UpdateWorldTransform() const;
|
||
|
||
friend class GameObject;
|
||
};
|
||
|
||
// 渲染组件(继承Component)
|
||
class RenderMeshComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
ResourceGUID GetMesh() const { return m_meshGuid; }
|
||
void SetMesh(const ResourceGUID& guid);
|
||
|
||
ResourceGUID GetMaterial() const { return m_materialGuid; }
|
||
void SetMaterial(const ResourceGUID& guid);
|
||
|
||
bool GetCastShadows() const { return m_castShadows; }
|
||
void SetCastShadows(bool cast) { m_castShadows = cast; }
|
||
|
||
bool GetReceiveShadows() const { return m_receiveShadows; }
|
||
void SetReceiveShadows(bool receive) { m_receiveShadows = receive; }
|
||
|
||
private:
|
||
ResourceGUID m_meshGuid;
|
||
ResourceGUID m_materialGuid;
|
||
bool m_castShadows = true;
|
||
bool m_receiveShadows = true;
|
||
};
|
||
|
||
// 光源组件 - 继承Component(类Unity Light)
|
||
class RenderLightComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class LightType : uint8_t {
|
||
Directional,
|
||
Point,
|
||
Spot,
|
||
Area
|
||
};
|
||
|
||
void SetLightType(LightType type) { m_type = type; }
|
||
LightType GetLightType() const { return m_type; }
|
||
|
||
void SetColor(const Vector3& color) { m_color = color; }
|
||
Vector3 GetColor() const { return m_color; }
|
||
|
||
void SetIntensity(float intensity) { m_intensity = intensity; }
|
||
float GetIntensity() const { return m_intensity; }
|
||
|
||
void SetRange(float range) { m_range = range; }
|
||
float GetRange() const { return m_range; }
|
||
|
||
void SetSpotAngle(float angle) { m_spotAngle = angle; }
|
||
float GetSpotAngle() const { return m_spotAngle; }
|
||
|
||
void SetCastShadows(bool cast) { m_castShadows = cast; }
|
||
bool GetCastShadows() const { return m_castShadows; }
|
||
|
||
void SetShadowResolution(uint32_t resolution) { m_shadowResolution = resolution; }
|
||
uint32_t GetShadowResolution() const { return m_shadowResolution; }
|
||
|
||
void SetCullingMask(int32_t mask) { m_cullingMask = mask; }
|
||
int32_t GetCullingMask() const { return m_cullingMask; }
|
||
|
||
private:
|
||
LightType m_type = LightType::Point;
|
||
Vector3 m_color = Vector3::One();
|
||
float m_intensity = 1.0f;
|
||
float m_range = 10.0f;
|
||
float m_spotAngle = 30.0f;
|
||
float m_penumbraAngle = 5.0f;
|
||
bool m_castShadows = true;
|
||
uint32_t m_shadowResolution = 1024;
|
||
float m_shadowBias = 0.005f;
|
||
float m_normalOffsetBias = 0.001f;
|
||
float m_nearPlane = 0.1f;
|
||
int32_t m_cullingMask = -1;
|
||
float m_intensityVariation = 0.0f;
|
||
ResourceGUID m_cookieTextureGuid = ResourceGUID::Invalid;
|
||
float m_cookieSize = 5.0f;
|
||
};
|
||
|
||
// 相机组件 - 继承Component(类Unity Camera)
|
||
class CameraComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class ProjectionType : uint8_t {
|
||
Perspective,
|
||
Orthographic
|
||
};
|
||
|
||
void SetProjectionType(ProjectionType type) { m_projectionType = type; }
|
||
ProjectionType GetProjectionType() const { return m_projectionType; }
|
||
|
||
void SetFieldOfView(float fov) { m_fieldOfView = fov; }
|
||
float GetFieldOfView() const { return m_fieldOfView; }
|
||
|
||
void SetOrthographicSize(float size) { m_orthographicSize = size; }
|
||
float GetOrthographicSize() const { return m_orthographicSize; }
|
||
|
||
void SetNearClipPlane(float near) { m_nearPlane = near; }
|
||
float GetNearClipPlane() const { return m_nearPlane; }
|
||
|
||
void SetFarClipPlane(float far) { m_farPlane = far; }
|
||
float GetFarClipPlane() const { return m_farPlane; }
|
||
|
||
void SetViewport(const Rect& rect) { m_viewportRect = rect; }
|
||
const Rect& GetViewport() const { return m_viewportRect; }
|
||
|
||
void SetCullingMask(int32_t mask) { m_cullingMask = mask; }
|
||
int32_t GetCullingMask() const { return m_cullingMask; }
|
||
|
||
void SetDepth(float depth) { m_depth = depth; }
|
||
float GetDepth() const { return m_depth; }
|
||
|
||
Matrix4x4 GetViewMatrix() const;
|
||
Matrix4x4 GetProjectionMatrix() const;
|
||
Matrix4x4 GetViewProjectionMatrix() const;
|
||
|
||
Vector3 ScreenToWorldPoint(const Vector3& screenPoint) const;
|
||
Vector3 WorldToScreenPoint(const Vector3& worldPoint) const;
|
||
Ray ScreenPointToRay(const Vector2& screenPoint) const;
|
||
|
||
Frustum& GetFrustum() { return m_frustum; }
|
||
|
||
private:
|
||
ProjectionType m_projectionType = ProjectionType::Perspective;
|
||
float m_fieldOfView = 60.0f;
|
||
float m_orthographicSize = 5.0f;
|
||
float m_nearPlane = 0.1f;
|
||
float m_farPlane = 1000.0f;
|
||
float m_aspectRatio = 16.0f / 9.0f;
|
||
Rect m_viewportRect = Rect(0, 0, 1, 1);
|
||
float m_depth = 0.0f;
|
||
int32_t m_cullingMask = -1;
|
||
Frustum m_frustum;
|
||
};
|
||
|
||
// 物理组件 - 继承Component(类Unity Rigidbody)
|
||
class RigidBodyComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void FixedUpdate() override;
|
||
void OnEnable() override;
|
||
void OnDisable() override;
|
||
void OnDestroy() override;
|
||
|
||
// 物理回调(类Unity)
|
||
void OnCollisionEnter(const Collision& collision) override;
|
||
void OnCollisionStay(const Collision& collision) override;
|
||
void OnCollisionExit(const Collision& collision) override;
|
||
void OnTriggerEnter(Collider* other) override;
|
||
void OnTriggerStay(Collider* other) override;
|
||
void OnTriggerExit(Collider* other) override;
|
||
|
||
enum class BodyType : uint8_t {
|
||
Dynamic,
|
||
Kinematic,
|
||
Static
|
||
};
|
||
|
||
void SetBodyType(BodyType type) { m_bodyType = type; }
|
||
BodyType GetBodyType() const { return m_bodyType; }
|
||
|
||
void SetMass(float mass) { m_mass = mass; }
|
||
float GetMass() const { return m_mass; }
|
||
|
||
void SetLinearDamping(float damping) { m_linearDamping = damping; }
|
||
float GetLinearDamping() const { return m_linearDamping; }
|
||
|
||
void SetAngularDamping(float damping) { m_angularDamping = damping; }
|
||
float GetAngularDamping() const { return m_angularDamping; }
|
||
|
||
void AddForce(const Vector3& force, ForceMode mode = ForceMode::Force);
|
||
void AddForceAtPosition(const Vector3& force, const Vector3& position, ForceMode mode = ForceMode::Force);
|
||
void AddTorque(const Vector3& torque, ForceMode mode = ForceMode::Force);
|
||
|
||
void SetVelocity(const Vector3& velocity);
|
||
Vector3 GetVelocity() const;
|
||
|
||
void SetAngularVelocity(const Vector3& velocity);
|
||
Vector3 GetAngularVelocity() const;
|
||
|
||
void SetUseGravity(bool use) { m_useGravity = use; }
|
||
bool IsUsingGravity() const { return m_useGravity; }
|
||
|
||
void SetIsKinematic(bool kinematic);
|
||
bool IsKinematic() const;
|
||
|
||
enum class InterpolateMode : uint8_t {
|
||
None,
|
||
Interpolate,
|
||
Extrapolate
|
||
};
|
||
|
||
void SetInterpolate(InterpolateMode mode);
|
||
InterpolateMode GetInterpolate() const { return m_interpolateMode; }
|
||
|
||
// 获取物理引擎内部句柄(用于 PhysicsWorld 调用,避免 GameObject* 悬空指针)
|
||
void* GetPhysicsHandle() const { return m_physicsHandle; }
|
||
void SetPhysicsHandle(void* handle) { m_physicsHandle = handle; }
|
||
|
||
private:
|
||
BodyType m_bodyType = BodyType::Dynamic;
|
||
float m_mass = 1.0f;
|
||
float m_linearDamping = 0.0f;
|
||
float m_angularDamping = 0.05f;
|
||
Vector3 m_velocity;
|
||
Vector3 m_angularVelocity;
|
||
bool m_useGravity = true;
|
||
InterpolateMode m_interpolateMode = InterpolateMode::None;
|
||
|
||
// 物理引擎内部句柄(由 PhysicsWorld 设置)
|
||
void* m_physicsHandle = nullptr;
|
||
};
|
||
|
||
// 碰撞组件 - 继承Component(类Unity Collider)
|
||
class ColliderComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
|
||
enum class ShapeType : uint8_t {
|
||
Box,
|
||
Sphere,
|
||
Capsule,
|
||
Mesh,
|
||
ConvexHull
|
||
};
|
||
|
||
void SetShapeType(ShapeType type) { m_shapeType = type; }
|
||
ShapeType GetShapeType() const { return m_shapeType; }
|
||
|
||
void SetCenter(const Vector3& center) { m_center = center; }
|
||
Vector3 GetCenter() const { return m_center; }
|
||
|
||
void SetSize(const Vector3& size) { m_boxSize = size; }
|
||
Vector3 GetSize() const { return m_boxSize; }
|
||
|
||
void SetRadius(float radius) { m_sphereRadius = radius; }
|
||
float GetRadius() const { return m_sphereRadius; }
|
||
|
||
void SetIsTrigger(bool trigger) { m_isTrigger = trigger; }
|
||
bool IsTrigger() const { return m_isTrigger; }
|
||
|
||
void SetMaterial(const ResourceGUID& guid);
|
||
ResourceGUID GetMaterial() const { return m_materialGuid; }
|
||
|
||
private:
|
||
ShapeType m_shapeType = ShapeType::Box;
|
||
Vector3 m_boxSize = Vector3::One();
|
||
float m_sphereRadius = 0.5f;
|
||
float m_capsuleRadius = 0.5f;
|
||
float m_capsuleHeight = 2.0f;
|
||
|
||
Vector3 m_center = Vector3::Zero();
|
||
Quaternion m_rotation = Quaternion::Identity();
|
||
|
||
int32_t m_layer = 0;
|
||
int32_t m_mask = -1;
|
||
|
||
float m_friction = 0.5f;
|
||
float m_restitution = 0.0f;
|
||
|
||
bool m_isTrigger = false;
|
||
bool m_convex = true;
|
||
|
||
ResourceGUID m_materialGuid = ResourceGUID::Invalid;
|
||
ResourceGUID m_meshGuid = ResourceGUID::Invalid;
|
||
|
||
// 物理引擎内部句柄(由 PhysicsWorld 设置)
|
||
void* m_physicsHandle = nullptr;
|
||
};
|
||
|
||
// 关节组件 - 继承Component(类Unity Joint)
|
||
class JointComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void OnDestroy() override;
|
||
|
||
enum class Type : uint8_t {
|
||
Hinge, // 铰链关节
|
||
Slider, // 滑块关节
|
||
Spring, // 弹簧关节
|
||
Fixed, // 固定关节
|
||
Configurable, // 可配置关节
|
||
Character // 角色关节
|
||
};
|
||
|
||
enum class Axis {
|
||
X, Y, Z
|
||
};
|
||
|
||
void SetJointType(Type type) { m_jointType = type; }
|
||
Type GetJointType() const { return m_jointType; }
|
||
|
||
void SetConnectedBody(GameObject* body) { m_connectedBody = body; }
|
||
GameObject* GetConnectedBody() const { return m_connectedBody; }
|
||
|
||
void SetAnchor(const Vector3& anchor) { m_anchor = anchor; }
|
||
Vector3 GetAnchor() const { return m_anchor; }
|
||
|
||
void SetAxis(const Vector3& axis) { m_axis = axis; }
|
||
Vector3 GetAxis() const { return m_axis; }
|
||
|
||
void SetBreakForce(float force) { m_breakForce = force; }
|
||
float GetBreakForce() const { return m_breakForce; }
|
||
|
||
void SetBreakTorque(float torque) { m_breakTorque = torque; }
|
||
float GetBreakTorque() const { return m_breakTorque; }
|
||
|
||
void SetEnableCollision(bool enable) { m_enableCollision = enable; }
|
||
bool GetEnableCollision() const { return m_enableCollision; }
|
||
|
||
bool IsBroken() const { return m_broken; }
|
||
|
||
private:
|
||
Type m_jointType = Type::Fixed;
|
||
GameObject* m_connectedBody = nullptr;
|
||
|
||
Vector3 m_anchor = Vector3::Zero();
|
||
Vector3 m_axis = Vector3::Up();
|
||
Vector3 m_secondaryAxis = Vector3::Right();
|
||
|
||
float m_breakForce = INFINITY;
|
||
float m_breakTorque = INFINITY;
|
||
bool m_enableCollision = false;
|
||
bool m_broken = false;
|
||
|
||
void* m_physicsJoint = nullptr;
|
||
};
|
||
|
||
// 音频源组件(继承Component)
|
||
class AudioSourceComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
void OnEnable() override;
|
||
void OnDisable() override;
|
||
void OnDestroy() override;
|
||
|
||
void Play();
|
||
void Stop();
|
||
void Pause();
|
||
|
||
bool IsPlaying() const;
|
||
bool IsPaused() const;
|
||
|
||
void SetClip(const ResourceGUID& guid);
|
||
ResourceGUID GetClip() const { return m_clipGuid; }
|
||
|
||
void SetLoop(bool loop) { m_loop = loop; }
|
||
bool GetLoop() const { return m_loop; }
|
||
|
||
void SetVolume(float volume) { m_volume = volume; }
|
||
float GetVolume() const { return m_volume; }
|
||
|
||
void SetPitch(float pitch) { m_pitch = pitch; }
|
||
float GetPitch() const { return m_pitch; }
|
||
|
||
void SetSpatialBlend(float blend) { m_spatialBlend = blend; }
|
||
float GetSpatialBlend() const { return m_spatialBlend; }
|
||
|
||
private:
|
||
ResourceGUID m_clipGuid;
|
||
bool m_playOnAwake = false;
|
||
bool m_loop = false;
|
||
bool m_isPlaying = false;
|
||
bool m_isPaused = false;
|
||
float m_volume = 1.0f;
|
||
float m_pitch = 1.0f;
|
||
float m_spatialBlend = 1.0f;
|
||
float m_minDistance = 1.0f;
|
||
float m_maxDistance = 500.0f;
|
||
};
|
||
|
||
// 音频监听器组件(继承Component)
|
||
class AudioListenerComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
|
||
void SetDopplerFactor(float factor) { m_dopplerFactor = factor; }
|
||
float GetDopplerFactor() const { return m_dopplerFactor; }
|
||
|
||
void SetMasterVolume(float volume) { m_masterVolume = volume; }
|
||
float GetMasterVolume() const { return m_masterVolume; }
|
||
|
||
private:
|
||
float m_dopplerFactor = 1.0f;
|
||
float m_masterVolume = 1.0f;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 3.5 场景 (Scene)
|
||
|
||
> 说明:传统Unity的Scene直接管理GameObject列表,没有World中间层。
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
// 场景(类Unity Scene)
|
||
// 直接管理GameObject列表,不需要World
|
||
class Scene {
|
||
public:
|
||
Scene();
|
||
~Scene();
|
||
|
||
// 场景名称
|
||
const String& GetName() const { return m_name; }
|
||
void SetName(const String& name) { m_name = name; }
|
||
|
||
// GameObject管理(类Unity Scene API)
|
||
GameObject* CreateGameObject(const String& name = "GameObject") {
|
||
GameObject::ConstructParams params;
|
||
params.name = name;
|
||
params.parent = nullptr;
|
||
params.active = true;
|
||
|
||
GameObject* obj = GameObject::Create(params);
|
||
obj->m_scene = this;
|
||
AddGameObject(obj);
|
||
return obj;
|
||
}
|
||
|
||
GameObject* CreateGameObject(const String& name, GameObject* parent) {
|
||
GameObject::ConstructParams params;
|
||
params.name = name;
|
||
params.parent = parent;
|
||
params.active = true;
|
||
|
||
GameObject* obj = GameObject::Create(params);
|
||
obj->m_scene = this;
|
||
AddGameObject(obj);
|
||
return obj;
|
||
}
|
||
|
||
void DestroyGameObject(GameObject* obj);
|
||
|
||
// 根GameObject(没有父对象的顶层GameObject,从所有GameObject中筛选)
|
||
// 注意:此方法为O(n)复杂度,与Unity的Scene.GetRootGameObjects行为一致
|
||
// Unity也不缓存根对象,因为GameObject层级变化频繁,缓存维护成本可能更高
|
||
std::vector<GameObject*> GetRootGameObjects() const {
|
||
std::vector<GameObject*> roots;
|
||
roots.reserve(m_gameObjects.size() / 2); // 预分配合理容量
|
||
for (auto& obj : m_gameObjects) {
|
||
if (obj->GetParent() == nullptr) {
|
||
roots.push_back(obj.get());
|
||
}
|
||
}
|
||
return roots;
|
||
}
|
||
|
||
// 查找
|
||
GameObject* Find(const String& name) const;
|
||
GameObject* FindGameObjectWithTag(const String& tag) const;
|
||
std::vector<GameObject*> FindGameObjectsWithTag(const String& tag) const;
|
||
template<typename T>
|
||
std::vector<T*> FindObjectsOfType() const;
|
||
T* FindObjectOfType() const;
|
||
|
||
// 激活状态
|
||
bool IsActive() const { return m_isActive; }
|
||
void SetActive(bool active);
|
||
|
||
// 生命周期
|
||
void Load(const String& filePath);
|
||
void LoadAsync(const String& filePath, std::function<void()> callback);
|
||
void Save(const String& filePath);
|
||
|
||
// 更新(内部调用)
|
||
void Update(float deltaTime);
|
||
void FixedUpdate(float fixedDeltaTime);
|
||
void LateUpdate(float deltaTime);
|
||
|
||
// 调试
|
||
void DebugDraw();
|
||
int GetObjectCount() const { return m_gameObjects.size(); }
|
||
|
||
private:
|
||
void AddGameObject(GameObject* obj);
|
||
void RemoveGameObject(GameObject* obj);
|
||
|
||
String m_name;
|
||
std::vector<std::unique_ptr<GameObject>> m_gameObjects;
|
||
bool m_isActive = true;
|
||
|
||
friend class GameObject;
|
||
friend class SceneManager;
|
||
};
|
||
|
||
// 场景管理器
|
||
class SceneManager {
|
||
public:
|
||
static SceneManager& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
// 场景操作
|
||
Scene* CreateScene(const String& name);
|
||
void LoadScene(const String& filePath);
|
||
void LoadSceneAsync(const String& filePath, std::function<void(Scene*)> callback);
|
||
void UnloadScene(Scene* scene);
|
||
void UnloadScene(const String& sceneName);
|
||
|
||
// 活动场景
|
||
void SetActiveScene(Scene* scene);
|
||
void SetActiveScene(const String& sceneName);
|
||
Scene* GetActiveScene() const;
|
||
|
||
// 查找
|
||
Scene* GetScene(const String& name) const;
|
||
std::vector<Scene*> GetAllScenes() const;
|
||
|
||
// 更新
|
||
void Update(float deltaTime);
|
||
void FixedUpdate(float fixedDeltaTime);
|
||
void LateUpdate(float deltaTime);
|
||
|
||
// 事件
|
||
Event<Scene*> OnSceneLoaded;
|
||
Event<Scene*> OnSceneUnloaded;
|
||
Event<Scene*> OnActiveSceneChanged;
|
||
|
||
private:
|
||
SceneManager() = default;
|
||
|
||
std::vector<std::unique_ptr<Scene>> m_scenes;
|
||
Scene* m_activeScene = nullptr;
|
||
Scene* m_loadingScene = nullptr;
|
||
|
||
std::unordered_map<String, Scene*> m_sceneNameMap;
|
||
std::function<void(Scene*)> m_loadCallback;
|
||
bool m_loading = false;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第四章 渲染系统 (Renderer)
|
||
|
||
> **架构说明**:
|
||
> - **RenderGraph** - 高级渲染管线抽象,定义 Pass 之间的依赖关系和资源流
|
||
> - **RenderContext** - 低级渲染上下文,管理 GPU 资源和执行具体的渲染命令
|
||
> - 关系:RenderGraph 是声明式的渲染描述,RenderContext 是执行层
|
||
|
||
### 4.1 渲染系统架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ Rendering Pipeline │
|
||
├─────────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ Render Pipeline Manager │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Render Graph Builder │ │
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||
│ │ │ Pass 1 │ │ Pass 2 │ │ Pass 3 │ │ Pass N │ │ │
|
||
│ │ │ G-Buffer │ │ Lighting │ │ Shadow │ │ Post │ │ │
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Render Passes │ │
|
||
│ │ │ │
|
||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
||
│ │ │ GBuffer │→ │ Shadow │→ │ Deferred │→ │ Forward │ │ │
|
||
│ │ │ Pass │ │ Pass │ │ Lighting │ │ Pass │ │ │
|
||
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
||
│ │ ↓ ↓ ↓ ↓ │ │
|
||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
||
│ │ │ Depth │ │ Shadow │ │ SSAO │ │ Alpha │ │ │
|
||
│ │ │ Pre-Pass │ │ Update │ │ Pass │ │ Blend │ │ │
|
||
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
||
│ │ ↓ │ │
|
||
│ │ ┌────────────────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ Post-Processing │ │ │
|
||
│ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │
|
||
│ │ │ │ SSAO │ │ SSR │ │ Bloom │ │ Tone │ │ FXAA │ │ │ │
|
||
│ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │
|
||
│ │ └────────────────────────────────────────────────────────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ GPU Resources │ │
|
||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
||
│ │ │ Vertex │ │ Index │ │ Uniform │ │ Texture │ │ Render │ │ │
|
||
│ │ │ Buffer │ │ Buffer │ │ Buffer │ │ Sampler │ │ Target │ │ │
|
||
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 渲染抽象层
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Rendering {
|
||
|
||
enum class ResourceState {
|
||
Undefined,
|
||
RenderTarget,
|
||
DepthStencil,
|
||
ShaderResource,
|
||
UnorderedAccess,
|
||
CopySrc,
|
||
CopyDst,
|
||
Present
|
||
};
|
||
|
||
struct ResourceDesc {
|
||
ResourceType type;
|
||
uint32_t width = 1;
|
||
uint32_t height = 1;
|
||
uint32_t depth = 1;
|
||
uint32_t mipLevels = 1;
|
||
uint32_t arraySize = 1;
|
||
Format format = Format::Unknown;
|
||
SampleCount sampleCount = SampleCount::Count1;
|
||
ResourceState initialState = ResourceState::Undefined;
|
||
bool cpuAccessible = false;
|
||
bool randomAccess = false;
|
||
|
||
MemoryUsage memoryUsage = MemoryUsage::Default;
|
||
|
||
String name;
|
||
};
|
||
|
||
class IRenderDevice {
|
||
public:
|
||
virtual ~IRenderDevice() = default;
|
||
|
||
virtual const char* GetApiName() const = 0;
|
||
virtual const char* GetDriverVersion() const = 0;
|
||
virtual uint64_t GetDeviceId() const = 0;
|
||
virtual uint64_t GetVendorId() const = 0;
|
||
|
||
virtual bool SupportsRaytracing() const = 0;
|
||
virtual bool SupportsMeshShaders() const = 0;
|
||
virtual bool SupportsVariableRateShading() const = 0;
|
||
virtual bool SupportsSamplerFeedback() const = 0;
|
||
virtual uint32_t GetMaxTextureSize() const = 0;
|
||
virtual uint32_t GetMaxUBOSize() const = 0;
|
||
virtual uint32_t GetMaxMSAA() const = 0;
|
||
|
||
virtual std::unique_ptr<RenderTexture> CreateTexture(const ResourceDesc& desc) = 0;
|
||
virtual std::unique_ptr<RenderBuffer> CreateBuffer(const ResourceDesc& desc, const void* initialData = nullptr) = 0;
|
||
virtual std::unique_ptr<Shader> CreateShader(const ShaderDesc& desc) = 0;
|
||
virtual std::unique_ptr<Pipeline> CreatePipeline(const PipelineDesc& desc) = 0;
|
||
virtual std::unique_ptr<RenderPass> CreateRenderPass(const RenderPassDesc& desc) = 0;
|
||
|
||
virtual ICommandQueue* GetGraphicsQueue() = 0;
|
||
virtual ICommandQueue* GetComputeQueue() = 0;
|
||
virtual ICommandQueue* GetCopyQueue() = 0;
|
||
|
||
virtual std::unique_ptr<IFence> CreateFence() = 0;
|
||
virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0;
|
||
virtual std::unique_ptr<IQueryHeap> CreateQueryHeap(const QueryHeapDesc& desc) = 0;
|
||
};
|
||
|
||
class ICommandList {
|
||
public:
|
||
virtual ~ICommandList() = default;
|
||
|
||
virtual void TransitionBarrier(const IResource* resource, ResourceState newState) = 0;
|
||
virtual void UAVBarrier(const IResource* resource) = 0;
|
||
virtual void FlushBarriers() = 0;
|
||
|
||
virtual void SetPipeline(const IPipeline* pipeline) = 0;
|
||
virtual void SetVertexBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0;
|
||
virtual void SetIndexBuffer(const IBuffer* buffer, IndexType indexType, uint64_t offset = 0) = 0;
|
||
virtual void SetConstantBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0;
|
||
virtual void SetShaderResource(uint32_t slot, const IResource* resource) = 0;
|
||
virtual void SetSampler(uint32_t slot, const ISampler* sampler) = 0;
|
||
|
||
virtual void Draw(uint32_t vertexCount, uint32_t firstVertex = 0) = 0;
|
||
virtual void DrawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, int32_t baseVertex = 0) = 0;
|
||
virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount,
|
||
uint32_t firstVertex = 0, uint32_t firstInstance = 0) = 0;
|
||
virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount,
|
||
uint32_t firstIndex = 0, int32_t baseVertex = 0, uint32_t firstInstance = 0) = 0;
|
||
|
||
virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0;
|
||
|
||
virtual void BuildAccelerationStructure(const RaytracingBuildDesc& desc) = 0;
|
||
virtual void SetRaytracingPipeline(const IPipeline* pipeline) = 0;
|
||
virtual void DispatchRays(const DispatchRaysDesc& desc) = 0;
|
||
|
||
virtual void BeginRenderPass(const RenderPassBeginDesc& desc) = 0;
|
||
virtual void EndRenderPass() = 0;
|
||
|
||
virtual void CopyResource(IResource* dst, const IResource* src) = 0;
|
||
virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, const IBuffer* src, uint64_t srcOffset, uint64_t size) = 0;
|
||
|
||
virtual void BeginQuery(IQueryHeap* heap, uint32_t index) = 0;
|
||
virtual void EndQuery(IQueryHeap* heap, uint32_t index) = 0;
|
||
|
||
virtual void SetMarker(const char* name, uint32_t color) = 0;
|
||
virtual void BeginEvent(const char* name, uint32_t color) = 0;
|
||
virtual void EndEvent() = 0;
|
||
};
|
||
|
||
class RenderContext {
|
||
public:
|
||
// 前向声明
|
||
class GBufferPass;
|
||
class LightingPass;
|
||
class ShadowPass;
|
||
class PostProcessPass;
|
||
|
||
// 创建和销毁(支持多实例)
|
||
static RenderContext* Create(const RenderContextDesc& desc);
|
||
static void Destroy(RenderContext* context);
|
||
|
||
// 获取主上下文(默认上下文,用于单窗口场景)
|
||
static RenderContext* GetMain();
|
||
|
||
void Initialize(const RenderContextDesc& desc);
|
||
void Shutdown();
|
||
|
||
IRenderDevice* GetDevice() { return m_device.get(); }
|
||
|
||
void BeginFrame();
|
||
void EndFrame();
|
||
|
||
ICommandList* GetMainCommandList() { return m_mainCommandList.get(); }
|
||
|
||
void SetRenderTarget(const RenderTarget& target);
|
||
void SetViewport(const Viewport& viewport);
|
||
void SetScissorRect(const Rect& rect);
|
||
|
||
void RenderScene(const SceneRenderDesc& desc);
|
||
void ApplyPostProcessing(const PostProcessDesc& desc);
|
||
|
||
void CaptureFrame(const String& filePath);
|
||
void ToggleDebugView();
|
||
|
||
private:
|
||
std::unique_ptr<IRenderDevice> m_device;
|
||
std::unique_ptr<ICommandList> m_mainCommandList;
|
||
std::unique_ptr<ISwapChain> m_swapChain;
|
||
|
||
std::unique_ptr<GBufferPass> m_gBufferPass;
|
||
std::unique_ptr<LightingPass> m_lightingPass;
|
||
std::unique_ptr<ShadowPass> m_shadowPass;
|
||
std::unique_ptr<PostProcessPass> m_postProcessPass;
|
||
|
||
uint32_t m_frameIndex = 0;
|
||
uint64_t m_frameCount = 0;
|
||
|
||
// 静态主上下文(用于 GetMain())
|
||
static RenderContext* s_mainContext;
|
||
};
|
||
|
||
class RenderTexture : public IResource {
|
||
public:
|
||
uint32_t GetWidth() const { return m_width; }
|
||
uint32_t GetHeight() const { return m_height; }
|
||
uint32_t GetMipLevels() const { return m_mipLevels; }
|
||
Format GetFormat() const { return m_format; }
|
||
|
||
void* GetNativeHandle() const { return m_nativeHandle; }
|
||
|
||
IShaderResourceView* GetSRV() { return m_srv.get(); }
|
||
IRenderTargetView* GetRTV() { return m_rtv.get(); }
|
||
IDepthStencilView* GetDSV() { return m_dsv.get(); }
|
||
|
||
void* Map();
|
||
void Unmap();
|
||
|
||
private:
|
||
uint32_t m_width, m_height;
|
||
uint32_t m_mipLevels;
|
||
Format m_format;
|
||
void* m_nativeHandle = nullptr;
|
||
|
||
std::unique_ptr<IShaderResourceView> m_srv;
|
||
std::unique_ptr<IRenderTargetView> m_rtv;
|
||
std::unique_ptr<IDepthStencilView> m_dsv;
|
||
};
|
||
|
||
class RenderBuffer : public IResource {
|
||
public:
|
||
uint64_t GetSize() const { return m_size; }
|
||
BufferUsage GetUsage() const { return m_usage; }
|
||
|
||
void* GetNativeHandle() const { return m_nativeHandle; }
|
||
|
||
void SetData(const void* data, uint64_t size, uint64_t offset = 0);
|
||
void* Map();
|
||
void Unmap();
|
||
|
||
private:
|
||
uint64_t m_size;
|
||
BufferUsage m_usage;
|
||
void* m_nativeHandle = nullptr;
|
||
};
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.3 渲染图 (Render Graph)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Rendering {
|
||
|
||
class RenderGraphResource {
|
||
public:
|
||
RenderGraphResource() = default;
|
||
RenderGraphResource(const String& name);
|
||
|
||
const String& GetName() const { return m_name; }
|
||
uint32_t GetIndex() const { return m_index; }
|
||
|
||
bool IsValid() const { return m_index != UINT32_MAX; }
|
||
operator bool() const { return IsValid(); }
|
||
|
||
private:
|
||
String m_name;
|
||
uint32_t m_index = UINT32_MAX;
|
||
friend class RenderGraph;
|
||
};
|
||
|
||
class RenderGraphPass {
|
||
public:
|
||
using ExecuteFn = std::function<void(RenderGraphPass&, ICommandList&)>;
|
||
|
||
RenderGraphPass(const String& name, PassType type);
|
||
|
||
RenderGraphResource Read(const String& resourceName);
|
||
RenderGraphResource Write(const String& resourceName);
|
||
RenderGraphResource ReadWrite(const String& resourceName, ResourceState initialState, ResourceState finalState);
|
||
|
||
void Execute(ExecuteFn&& fn);
|
||
void Execute() const;
|
||
|
||
void SetDebugColor(const Color& color);
|
||
|
||
const String& GetName() const { return m_name; }
|
||
PassType GetType() const { return m_type; }
|
||
const std::vector<RenderGraphResource>& GetReads() const { return m_reads; }
|
||
const std::vector<RenderGraphResource>& GetWrites() const { return m_writes; }
|
||
|
||
private:
|
||
String m_name;
|
||
PassType m_type;
|
||
std::vector<RenderGraphResource> m_reads;
|
||
std::vector<RenderGraphResource> m_writes;
|
||
ExecuteFn m_executeFn;
|
||
Color m_debugColor;
|
||
|
||
friend class RenderGraph;
|
||
};
|
||
|
||
class RenderGraph {
|
||
public:
|
||
RenderGraph();
|
||
~RenderGraph();
|
||
|
||
RenderGraphResource CreateTexture(const String& name, const TextureDesc& desc);
|
||
RenderGraphResource CreateBuffer(const String& name, const BufferDesc& desc);
|
||
|
||
RenderGraphPass& AddPass(const String& name, PassType type);
|
||
|
||
void Build();
|
||
void Execute(ICommandList* commandList);
|
||
|
||
void SetName(const String& name);
|
||
void Print() const;
|
||
void ExportToDot(const String& filePath) const;
|
||
|
||
void Clear();
|
||
|
||
private:
|
||
void Compile();
|
||
void Validate();
|
||
void SortPasses();
|
||
void AllocateResources();
|
||
|
||
struct ResourceInfo {
|
||
String name;
|
||
ResourceDesc desc;
|
||
ResourceState currentState;
|
||
uint32_t firstPassWrite = UINT32_MAX;
|
||
uint32_t lastPassRead = UINT32_MAX;
|
||
bool imported = false;
|
||
};
|
||
|
||
struct PassInfo {
|
||
String name;
|
||
PassType type;
|
||
std::vector<uint32_t> reads;
|
||
std::vector<uint32_t> writes;
|
||
std::function<void(RenderGraphPass&, ICommandList&)> executeFn;
|
||
};
|
||
|
||
std::vector<ResourceInfo> m_resources;
|
||
std::vector<PassInfo> m_passes;
|
||
std::unordered_map<String, uint32_t> m_resourceIndex;
|
||
|
||
bool m_built = false;
|
||
};
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第五章 资源系统 (Resource System)
|
||
|
||
### 5.1 资源管理架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ Resource Management │
|
||
├─────────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ Asset Database │ │
|
||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||
│ │ │ GUID │ │ Path │ │ Meta │ │ │
|
||
│ │ │ 映射表 │ │ 索引 │ │ 数据 │ │ │
|
||
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Resource Manager │ │
|
||
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ Resource Loader Registry │ │ │
|
||
│ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │
|
||
│ │ │ │ Mesh │ │ Texture│ │ Audio │ │ Material│ │ Shader │ │ │ │
|
||
│ │ │ │ Loader │ │ Loader │ │ Loader │ │ Loader │ │ Loader │ │ │ │
|
||
│ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │
|
||
│ │ └───────────────────────────────────────────────────────────────┘ │ │
|
||
│ │ │ │ │
|
||
│ │ ┌──────────────────────────▼────────────────────────────────────┐ │ │
|
||
│ │ │ Resource Cache │ │ │
|
||
│ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │
|
||
│ │ │ │ LRU Cache │ │ │ │
|
||
│ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ │
|
||
│ │ │ │ │ Resource│ │ Resource│ │ Resource│ │ Resource│ │ │ │ │
|
||
│ │ │ │ │ 1 │ │ 2 │ │ 3 │ │ N │ │ │ │ │
|
||
│ │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ │
|
||
│ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │
|
||
│ │ └───────────────────────────────────────────────────────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
|
||
│ │ Import Pipeline │ │
|
||
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
||
│ │ │ Import │→ │ Process │→ │ Cook │→ │ Package │→ │ Index │ │ │
|
||
│ │ │ 导入 │ │ 处理 │ │ 烘焙 │ │ 打包 │ │ 索引 │ │ │
|
||
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 资源系统实现
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Resources {
|
||
|
||
enum class ResourceType {
|
||
Unknown,
|
||
Mesh,
|
||
Texture,
|
||
Material,
|
||
Shader,
|
||
Audio,
|
||
Animation,
|
||
Skeleton,
|
||
Font,
|
||
Prefab,
|
||
Scene,
|
||
Script,
|
||
PhysicsMaterial,
|
||
NavMesh,
|
||
Video,
|
||
Custom
|
||
};
|
||
|
||
struct ResourceGUID {
|
||
static constexpr uint64_t INVALID = 0;
|
||
|
||
uint64_t value = INVALID;
|
||
|
||
bool IsValid() const { return value != INVALID; }
|
||
bool operator==(const ResourceGUID& other) const { return value == other.value; }
|
||
bool operator!=(const ResourceGUID& other) const { return value != other.value; }
|
||
|
||
String ToString() const;
|
||
static ResourceGUID FromString(const String& str);
|
||
|
||
struct Hash {
|
||
size_t operator()(const ResourceGUID& guid) const {
|
||
return std::hash<uint64_t>{}(guid.value);
|
||
}
|
||
};
|
||
};
|
||
|
||
class IResource {
|
||
public:
|
||
virtual ~IResource() = default;
|
||
|
||
virtual ResourceType GetType() const = 0;
|
||
virtual const String& GetName() const = 0;
|
||
virtual ResourceGUID GetGUID() const = 0;
|
||
|
||
virtual bool IsLoaded() const = 0;
|
||
virtual bool IsLoading() const = 0;
|
||
virtual float GetLoadingProgress() const = 0;
|
||
|
||
virtual void AddRef() = 0;
|
||
virtual void Release() = 0;
|
||
virtual uint32_t GetRefCount() const = 0;
|
||
|
||
virtual void Unload() = 0;
|
||
};
|
||
|
||
struct LoadRequest {
|
||
ResourceGUID guid;
|
||
ResourceType type;
|
||
std::function<void(IResource*)> callback;
|
||
std::function<void(float)> progressCallback;
|
||
bool async = true;
|
||
uint32_t priority = 0;
|
||
};
|
||
|
||
class IResourceLoader {
|
||
public:
|
||
virtual ~IResourceLoader() = default;
|
||
|
||
virtual ResourceType GetResourceType() const = 0;
|
||
virtual std::vector<String> GetSupportedExtensions() const = 0;
|
||
|
||
virtual bool CanLoad(const String& filePath) const = 0;
|
||
virtual bool Load(const String& filePath, IResource* resource) = 0;
|
||
virtual bool Save(const String& filePath, const IResource* resource) = 0;
|
||
|
||
virtual std::unique_ptr<IResource> CreateResource() = 0;
|
||
};
|
||
|
||
class ResourceRepository {
|
||
public:
|
||
void Initialize(const String& basePath);
|
||
void Shutdown();
|
||
|
||
std::unique_ptr<uint8_t[]> LoadRaw(const String& filePath, size_t& outSize);
|
||
std::unique_ptr<IStream> OpenStream(const String& filePath);
|
||
|
||
bool FileExists(const String& filePath);
|
||
bool DirectoryExists(const String& dirPath);
|
||
std::vector<String> GetFiles(const String& dirPath, const String& extension = "");
|
||
|
||
String GetFullPath(const String& relativePath);
|
||
String GetCachePath();
|
||
String GetSourcePath();
|
||
|
||
private:
|
||
String m_basePath;
|
||
String m_cachePath;
|
||
String m_sourcePath;
|
||
};
|
||
|
||
class ResourceCache {
|
||
public:
|
||
explicit ResourceCache(size_t maxMemory);
|
||
~ResourceCache();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void Add(const ResourceGUID& guid, IResource* resource);
|
||
IResource* Find(const ResourceGUID& guid);
|
||
void Remove(const ResourceGUID& guid);
|
||
void Clear();
|
||
|
||
void SetMaxMemory(size_t bytes);
|
||
size_t GetCurrentMemory() const;
|
||
size_t GetMaxMemory() const;
|
||
|
||
void Touch(const ResourceGUID& guid);
|
||
void Evict(size_t bytesToFree);
|
||
|
||
struct Stats {
|
||
uint32_t hitCount;
|
||
uint32_t missCount;
|
||
size_t memoryUsed;
|
||
size_t memoryReserved;
|
||
};
|
||
const Stats& GetStats() const;
|
||
|
||
private:
|
||
struct CacheEntry {
|
||
IResource* resource;
|
||
size_t memorySize;
|
||
uint64_t lastAccess;
|
||
};
|
||
|
||
std::unordered_map<ResourceGUID, CacheEntry, ResourceGUID::Hash> m_cache;
|
||
size_t m_maxMemory;
|
||
size_t m_currentMemory;
|
||
Stats m_stats;
|
||
};
|
||
|
||
class ResourceManager {
|
||
public:
|
||
static ResourceManager& Get();
|
||
|
||
void Initialize(const ResourceManagerConfig& config);
|
||
void Shutdown();
|
||
|
||
void RegisterLoader(std::unique_ptr<IResourceLoader> loader);
|
||
IResourceLoader* GetLoader(ResourceType type) const;
|
||
IResourceLoader* GetLoaderForFile(const String& filePath) const;
|
||
|
||
ResourceGUID Load(const String& filePath);
|
||
ResourceGUID LoadAsync(const String& filePath, const std::function<void(IResource*)>& callback);
|
||
|
||
template<typename T>
|
||
std::shared_ptr<T> Get(const ResourceGUID& guid);
|
||
|
||
template<typename T>
|
||
std::shared_ptr<T> Get(const String& filePath);
|
||
|
||
void AddRef(const ResourceGUID& guid);
|
||
void Release(const ResourceGUID& guid);
|
||
|
||
ResourceGUID FindByPath(const String& path) const;
|
||
String GetPath(const ResourceGUID& guid) const;
|
||
|
||
bool Reload(const ResourceGUID& guid);
|
||
void Unload(const ResourceGUID& guid);
|
||
void UnloadUnused();
|
||
|
||
void PrintStatistics();
|
||
|
||
void RebuildDatabase();
|
||
void ScanDirectory(const String& dirPath);
|
||
|
||
private:
|
||
ResourceManager() = default;
|
||
|
||
std::unordered_map<ResourceType, std::unique_ptr<IResourceLoader>> m_loaders;
|
||
std::unordered_map<ResourceGUID, std::shared_ptr<IResource>, ResourceGUID::Hash> m_resources;
|
||
std::unordered_map<String, ResourceGUID> m_pathToGUID;
|
||
std::unordered_map<ResourceGUID, String, ResourceGUID::Hash> m_guidToPath;
|
||
|
||
std::unique_ptr<ResourceCache> m_cache;
|
||
std::unique_ptr<ResourceRepository> m_repository;
|
||
|
||
std::unique_ptr<AssetDatabase> m_assetDatabase;
|
||
|
||
std::atomic<uint64_t> m_nextGuid{1};
|
||
};
|
||
|
||
template<typename T>
|
||
class ResourcePtr {
|
||
public:
|
||
ResourcePtr() = default;
|
||
|
||
explicit ResourcePtr(const ResourceGUID& guid)
|
||
: m_guid(guid), m_resource(ResourceManager::Get().Get<T>(guid)) {}
|
||
|
||
ResourcePtr(const ResourcePtr& other)
|
||
: m_guid(other.m_guid), m_resource(other.m_resource) {}
|
||
|
||
~ResourcePtr() {
|
||
if (m_guid.IsValid()) {
|
||
ResourceManager::Get().Release(m_guid);
|
||
}
|
||
}
|
||
|
||
T* Get() const { return m_resource.get(); }
|
||
T* operator->() const { return m_resource.get(); }
|
||
T& operator*() const { return *m_resource; }
|
||
|
||
bool IsValid() const { return m_resource != nullptr; }
|
||
explicit operator bool() const { return IsValid(); }
|
||
|
||
const ResourceGUID& GetGUID() const { return m_guid; }
|
||
|
||
private:
|
||
ResourceGUID m_guid;
|
||
std::shared_ptr<T> m_resource;
|
||
};
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第六章 场景系统 (Scene System)
|
||
|
||
> **架构说明**: Scene是Unity风格的场景,直接管理GameObject列表(没有World中间层),负责场景生命周期管理、资源加载和序列化。
|
||
|
||
### 6.1 场景管理
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Scene {
|
||
|
||
// 注意:GameObject和Transform定义在Components命名空间中
|
||
// Transform是GameObject的内置组件,包含父子层级关系
|
||
|
||
enum class SceneLoadFlags {
|
||
None = 0,
|
||
Async = 1 << 0,
|
||
Additive = 1 << 1,
|
||
Single = 1 << 2,
|
||
DontLoadAudio = 1 << 3,
|
||
DontCreatePhysics = 1 << 4,
|
||
SubScene = 1 << 5
|
||
};
|
||
|
||
inline SceneLoadFlags operator|(SceneLoadFlags a, SceneLoadFlags b) {
|
||
return static_cast<SceneLoadFlags>(static_cast<int>(a) | static_cast<int>(b));
|
||
}
|
||
|
||
inline SceneLoadFlags& operator|=(SceneLoadFlags& a, SceneLoadFlags b) {
|
||
a = a | b;
|
||
return a;
|
||
}
|
||
|
||
inline SceneLoadFlags operator&(SceneLoadFlags a, SceneLoadFlags b) {
|
||
return static_cast<SceneLoadFlags>(static_cast<int>(a) & static_cast<int>(b));
|
||
}
|
||
|
||
inline SceneLoadFlags& operator&=(SceneLoadFlags& a, SceneLoadFlags b) {
|
||
a = a & b;
|
||
return a;
|
||
}
|
||
|
||
inline bool HasFlag(SceneLoadFlags flags, SceneLoadFlags flag) {
|
||
return (static_cast<int>(flags) & static_cast<int>(flag)) != 0;
|
||
}
|
||
|
||
// 注意:SceneManager 定义在 XCEngine 命名空间中(第三章 3.5 节)
|
||
// 此处只保留场景相关的辅助类型和序列化器
|
||
|
||
// 场景序列化器
|
||
// 支持 JSON 和 Binary 两种格式
|
||
class SceneSerializer {
|
||
public:
|
||
// 序列化格式
|
||
enum class Format {
|
||
JSON,
|
||
Binary
|
||
};
|
||
|
||
// 序列化到文件
|
||
static void Serialize(const Scene& scene, const String& filePath, Format format = Format::JSON);
|
||
static std::unique_ptr<Scene> Deserialize(const String& filePath);
|
||
|
||
// JSON 序列化 (使用已存在的 Core 命名空间中的 JSON 库)
|
||
static void SerializeToJson(const Scene& scene, Core::JsonDocument& doc);
|
||
static void DeserializeFromJson(Scene& scene, const Core::JsonDocument& doc);
|
||
|
||
// Binary 序列化 (使用 Core::IStream)
|
||
static void SerializeToBinary(const Scene& scene, Core::IStream& stream);
|
||
static std::unique_ptr<Scene> DeserializeFromBinary(Core::IStream& stream);
|
||
|
||
private:
|
||
static void SerializeGameObject(const GameObject& gameObject, Core::JsonValue& parent);
|
||
static void DeserializeGameObject(GameObject& gameObject, const Core::JsonValue& data);
|
||
|
||
static void SerializeComponent(uint32_t componentTypeId, const void* component, Core::JsonValue& parent);
|
||
static void DeserializeComponent(uint32_t componentTypeId, const GameObject& gameObject, const Core::JsonValue& data);
|
||
};
|
||
|
||
// ============================================================================
|
||
// 序列化辅助类型 (需要在 Core 命名空间中定义)
|
||
// ============================================================================
|
||
|
||
namespace Core {
|
||
|
||
// 流接口
|
||
class IStream {
|
||
public:
|
||
virtual ~IStream() = default;
|
||
|
||
virtual bool IsValid() const = 0;
|
||
virtual size_t GetPosition() const = 0;
|
||
virtual size_t GetSize() const = 0;
|
||
|
||
virtual size_t Read(void* buffer, size_t size) = 0;
|
||
virtual size_t Write(const void* buffer, size_t size) = 0;
|
||
|
||
virtual void Seek(size_t position) = 0;
|
||
virtual void Skip(size_t bytes) = 0;
|
||
virtual void Flush() = 0;
|
||
|
||
virtual bool IsReading() const = 0;
|
||
virtual bool IsWriting() const = 0;
|
||
};
|
||
|
||
// JSON 文档
|
||
class JsonDocument {
|
||
public:
|
||
JsonDocument();
|
||
~JsonDocument();
|
||
|
||
void Parse(const String& json);
|
||
void Parse(const char* json, size_t length);
|
||
|
||
JsonValue& GetRoot();
|
||
const JsonValue& GetRoot() const;
|
||
|
||
String ToString() const;
|
||
|
||
bool HasParseError() const;
|
||
String GetParseError() const;
|
||
};
|
||
|
||
// JSON 值
|
||
class JsonValue {
|
||
public:
|
||
enum class Type {
|
||
Null,
|
||
Bool,
|
||
Int,
|
||
Float,
|
||
String,
|
||
Array,
|
||
Object
|
||
};
|
||
|
||
JsonValue();
|
||
JsonValue(bool value);
|
||
JsonValue(int32_t value);
|
||
JsonValue(int64_t value);
|
||
JsonValue(float value);
|
||
JsonValue(double value);
|
||
JsonValue(const String& value);
|
||
JsonValue(const char* value);
|
||
~JsonValue();
|
||
|
||
Type GetType() const { return m_type; }
|
||
|
||
// 值的获取
|
||
bool GetBool() const;
|
||
int32_t GetInt() const;
|
||
int64_t GetInt64() const;
|
||
float GetFloat() const;
|
||
double GetDouble() const;
|
||
const String& GetString() const;
|
||
|
||
// 数组/对象访问
|
||
size_t GetSize() const;
|
||
JsonValue& operator[](size_t index);
|
||
const JsonValue& operator[](size_t index) const;
|
||
JsonValue& operator[](const String& key);
|
||
const JsonValue& operator[](const String& key) const;
|
||
|
||
bool Has(const String& key) const;
|
||
|
||
// 修改
|
||
JsonValue& SetBool(bool value);
|
||
JsonValue& SetInt(int32_t value);
|
||
JsonValue& SetFloat(float value);
|
||
JsonValue& SetString(const String& value);
|
||
|
||
JsonValue& AddArrayElement();
|
||
JsonValue& AddObjectMember(const String& key);
|
||
|
||
void Clear();
|
||
|
||
private:
|
||
Type m_type = Type::Null;
|
||
// ... 具体成员
|
||
};
|
||
|
||
} // namespace Core
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第七章 物理系统 (Physics)
|
||
|
||
### 7.1 物理系统
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Physics {
|
||
|
||
// 碰撞检测查询标志
|
||
enum class QueryFlags : uint32_t {
|
||
None = 0,
|
||
Colliders = 1 << 0,
|
||
Rigidodies = 1 << 1,
|
||
Transforms = 1 << 2,
|
||
All = Colliders | Rigidodies | Transforms
|
||
};
|
||
|
||
// 力学模式 (类Unity ForceMode)
|
||
enum class ForceMode : uint8_t {
|
||
Force = 0, // 持续力 (质量单位)
|
||
Acceleration = 1, // 加速度 (无质量单位)
|
||
Impulse = 2, // 瞬时冲量 (质量单位)
|
||
VelocityChange = 3 // 速度变化 (无质量单位)
|
||
};
|
||
|
||
enum class CollisionShapeType {
|
||
Sphere,
|
||
Box,
|
||
Capsule,
|
||
ConvexMesh,
|
||
ConcaveMesh,
|
||
Heightfield,
|
||
Compound
|
||
};
|
||
|
||
struct CollisionLayer {
|
||
static constexpr uint32_t MaxLayers = 32;
|
||
static constexpr uint32_t Default = 0;
|
||
|
||
uint32_t id;
|
||
String name;
|
||
uint32_t mask;
|
||
};
|
||
|
||
struct PhysicsMaterial {
|
||
float friction = 0.5f;
|
||
float restitution = 0.0f;
|
||
float frictionCombine = 0;
|
||
float restitutionCombine = 0;
|
||
bool isTrigger = false;
|
||
|
||
float staticFriction = 0.5f;
|
||
float dynamicFriction = 0.5f;
|
||
};
|
||
|
||
struct RaycastHit {
|
||
GameObject* gameObject;
|
||
Vector3 point;
|
||
Vector3 normal;
|
||
float distance;
|
||
Vector2 uv;
|
||
int32_t faceIndex;
|
||
float fraction;
|
||
|
||
ColliderComponent* collider = nullptr;
|
||
};
|
||
|
||
// 碰撞信息 (类Unity Collision)
|
||
struct Collision {
|
||
GameObject* gameObject = nullptr;
|
||
ColliderComponent* collider = nullptr;
|
||
RigidBodyComponent* rigidBody = nullptr;
|
||
|
||
Vector3 relativeVelocity;
|
||
Vector3 contactPoint;
|
||
Vector3 contactNormal;
|
||
|
||
std::vector<Vector3> contacts;
|
||
std::vector<Vector3> normals;
|
||
};
|
||
|
||
// 2D碰撞信息 (类Unity Collision2D)
|
||
struct Collision2D {
|
||
GameObject* gameObject = nullptr;
|
||
Collider2DComponent* collider = nullptr;
|
||
RigidBody2DComponent* rigidBody = nullptr;
|
||
|
||
Vector2 relativeVelocity;
|
||
Vector2 contactPoint;
|
||
Vector2 contactNormal;
|
||
|
||
std::vector<Vector2> contacts;
|
||
std::vector<Vector2> normals;
|
||
|
||
float fraction = 0.0f;
|
||
int32_t faceID = 0;
|
||
};
|
||
|
||
// 2D碰撞体组件 (类Unity Collider2D)
|
||
class Collider2DComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
|
||
enum class ShapeType : uint8_t {
|
||
Box,
|
||
Circle,
|
||
Capsule,
|
||
Polygon,
|
||
Edge
|
||
};
|
||
|
||
void SetShapeType(ShapeType type) { m_shapeType = type; }
|
||
ShapeType GetShapeType() const { return m_shapeType; }
|
||
|
||
void SetOffset(const Vector2& offset) { m_offset = offset; }
|
||
Vector2 GetOffset() const { return m_offset; }
|
||
|
||
void SetDensity(float density) { m_density = density; }
|
||
float GetDensity() const { return m_density; }
|
||
|
||
void SetIsTrigger(bool trigger) { m_isTrigger = trigger; }
|
||
bool IsTrigger() const { return m_isTrigger; }
|
||
|
||
void SetUsedByEffector(bool use) { m_usedByEffector = use; }
|
||
bool IsUsedByEffector() const { return m_usedByEffector; }
|
||
|
||
private:
|
||
ShapeType m_shapeType = ShapeType::Box;
|
||
Vector2 m_offset = Vector2::Zero();
|
||
float m_density = 1.0f;
|
||
bool m_isTrigger = false;
|
||
bool m_usedByEffector = false;
|
||
|
||
void* m_physicsHandle = nullptr;
|
||
};
|
||
|
||
// 2D刚体组件 (类Unity Rigidbody2D)
|
||
class RigidBody2DComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void FixedUpdate() override;
|
||
|
||
enum class BodyType : uint8_t {
|
||
Dynamic,
|
||
Kinematic,
|
||
Static
|
||
};
|
||
|
||
enum class InterpolateMode : uint8_t {
|
||
None,
|
||
Interpolate,
|
||
Extrapolate
|
||
};
|
||
|
||
void SetBodyType(BodyType type) { m_bodyType = type; }
|
||
BodyType GetBodyType() const { return m_bodyType; }
|
||
|
||
void SetMass(float mass) { m_mass = mass; }
|
||
float GetMass() const { return m_mass; }
|
||
|
||
void SetLinearVelocity(const Vector2& velocity);
|
||
Vector2 GetLinearVelocity() const;
|
||
|
||
void SetAngularVelocity(float velocity);
|
||
float GetAngularVelocity() const;
|
||
|
||
void AddForce(const Vector2& force, ForceMode mode = ForceMode::Force);
|
||
void AddForceAtPosition(const Vector2& force, const Vector2& position, ForceMode mode = ForceMode::Force);
|
||
|
||
void SetGravityScale(float scale) { m_gravityScale = scale; }
|
||
float GetGravityScale() const { return m_gravityScale; }
|
||
|
||
void SetIsKinematic(bool kinematic) { m_kinematic = kinematic; }
|
||
bool IsKinematic() const { return m_kinematic; }
|
||
|
||
void SetInterpolateMode(InterpolateMode mode) { m_interpolateMode = mode; }
|
||
InterpolateMode GetInterpolateMode() const { return m_interpolateMode; }
|
||
|
||
void* GetPhysicsHandle() const { return m_physicsHandle; }
|
||
void SetPhysicsHandle(void* handle) { m_physicsHandle = handle; }
|
||
|
||
private:
|
||
BodyType m_bodyType = BodyType::Dynamic;
|
||
float m_mass = 1.0f;
|
||
Vector2 m_linearVelocity;
|
||
float m_angularVelocity = 0.0f;
|
||
float m_gravityScale = 1.0f;
|
||
bool m_kinematic = false;
|
||
InterpolateMode m_interpolateMode = InterpolateMode::None;
|
||
|
||
void* m_physicsHandle = nullptr;
|
||
};
|
||
|
||
struct CollisionEvent {
|
||
GameObject* gameObjectA;
|
||
GameObject* gameObjectB;
|
||
Vector3 point;
|
||
Vector3 normal;
|
||
Vector3 relativeVelocity;
|
||
|
||
enum class Type {
|
||
Enter,
|
||
Stay,
|
||
Exit
|
||
};
|
||
Type type;
|
||
};
|
||
|
||
class PhysicsWorld {
|
||
public:
|
||
PhysicsWorld();
|
||
~PhysicsWorld();
|
||
|
||
void Initialize(const PhysicsWorldDesc& desc);
|
||
void Shutdown();
|
||
|
||
void Simulate(float deltaTime);
|
||
void SetGravity(const Vector3& gravity);
|
||
Vector3 GetGravity() const { return m_gravity; }
|
||
|
||
// 物理组件注册(替代直接 SyncWithScene,通过组件系统同步)
|
||
void RegisterRigidBody(RigidBodyComponent* component);
|
||
void UnregisterRigidBody(RigidBodyComponent* component);
|
||
void RegisterCollider(ColliderComponent* component);
|
||
void UnregisterCollider(ColliderComponent* component);
|
||
|
||
bool Raycast(const Ray& ray, float maxDistance, RaycastHit& hit,
|
||
uint32_t layerMask = 0xFFFFFFFF, QueryFlags flags = QueryFlags::None);
|
||
bool RaycastMultiple(const Ray& ray, float maxDistance, std::vector<RaycastHit>& hits,
|
||
uint32_t layerMask = 0xFFFFFFFF, QueryFlags flags = QueryFlags::None);
|
||
|
||
bool CheckSphere(const Sphere& sphere, uint32_t layerMask = 0xFFFFFFFF);
|
||
bool CheckBox(const Box& box, uint32_t layerMask = 0xFFFFFFFF);
|
||
bool CheckCapsule(const Vector3& start, const Vector3& end, float radius,
|
||
uint32_t layerMask = 0xFFFFFFFF);
|
||
|
||
bool SphereCast(const Sphere& sphere, const Vector3& direction, float maxDistance,
|
||
RaycastHit& hit, uint32_t layerMask = 0xFFFFFFFF);
|
||
|
||
std::vector<GameObject*> OverlapSphere(const Sphere& sphere, uint32_t layerMask = 0xFFFFFFFF);
|
||
std::vector<GameObject*> OverlapBox(const Box& box, uint32_t layerMask = 0xFFFFFFFF);
|
||
|
||
// 使用 RigidBodyComponent* 代替 GameObject*,通过组件内部的句柄操作,避免悬空指针
|
||
void AddForce(RigidBodyComponent* component, const Vector3& force, ForceMode mode = ForceMode::Force);
|
||
void AddForceAtPosition(RigidBodyComponent* component, const Vector3& force, const Vector3& position,
|
||
ForceMode mode = ForceMode::Force);
|
||
void AddTorque(RigidBodyComponent* component, const Vector3& torque, ForceMode mode = ForceMode::Force);
|
||
|
||
void SetLinearVelocity(RigidBodyComponent* component, const Vector3& velocity);
|
||
void SetAngularVelocity(RigidBodyComponent* component, const Vector3& velocity);
|
||
Vector3 GetLinearVelocity(RigidBodyComponent* component) const;
|
||
Vector3 GetAngularVelocity(RigidBodyComponent* component) const;
|
||
|
||
void SetKinematic(RigidBodyComponent* component, bool kinematic);
|
||
|
||
// Joint 由 JointComponent 组件管理,不再由 PhysicsWorld 直接创建
|
||
|
||
Event<const CollisionEvent&> OnCollisionEnter;
|
||
Event<const CollisionEvent&> OnCollisionStay;
|
||
Event<const CollisionEvent&> OnCollisionExit;
|
||
Event<const CollisionEvent&> OnTriggerEnter;
|
||
Event<const CollisionEvent&> OnTriggerStay;
|
||
Event<const CollisionEvent&> OnTriggerExit;
|
||
|
||
void DebugDraw();
|
||
void SetDebugDrawEnabled(bool enabled);
|
||
|
||
private:
|
||
void* m_physicsBackend = nullptr;
|
||
|
||
Vector3 m_gravity = Vector3(0, -9.81f, 0);
|
||
|
||
std::vector<CollisionEvent> m_collisionEvents;
|
||
std::vector<CollisionEvent> m_triggerEvents;
|
||
|
||
bool m_debugDrawEnabled = false;
|
||
};
|
||
|
||
class CharacterControllerComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Update(float deltaTime) override;
|
||
void OnDestroy() override;
|
||
|
||
void Initialize(const CharacterControllerDesc& desc);
|
||
|
||
void Move(const Vector3& displacement);
|
||
void SetVelocity(const Vector3& velocity);
|
||
Vector3 GetVelocity() const { return m_velocity; }
|
||
|
||
bool IsGrounded() const { return m_grounded; }
|
||
Vector3 GetGroundNormal() const { return m_groundNormal; }
|
||
GameObject* GetGroundObject() const { return m_groundObject; }
|
||
|
||
void Jump(const Vector3& jumpForce);
|
||
void SetJumpEnabled(bool enabled);
|
||
|
||
void SetSlopeLimit(float angle);
|
||
void SetStepOffset(float height);
|
||
void SetSkinWidth(float width);
|
||
|
||
bool DetectCollision(const Vector3& position, const Vector3& direction, float distance);
|
||
|
||
private:
|
||
void UpdateGroundStatus();
|
||
void HandleCollision();
|
||
|
||
Vector3 m_velocity = Vector3::Zero();
|
||
Vector3 m_pendingForces = Vector3::Zero();
|
||
|
||
float m_slopeLimit = 45.0f;
|
||
float m_stepOffset = 0.5f;
|
||
float m_skinWidth = 0.02f;
|
||
float m_minDistance = 0.1f;
|
||
|
||
bool m_grounded = false;
|
||
bool m_jumpEnabled = true;
|
||
Vector3 m_groundNormal = Vector3::Up();
|
||
GameObject* m_groundObject = nullptr;
|
||
|
||
uint32_t m_layer = 0;
|
||
uint32_t m_collisionMask = 0xFFFFFFFF;
|
||
};
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第八章 音频系统 (Audio)
|
||
|
||
> **架构说明**: Unity风格的音频系统。音频源和监听器都是挂载在GameObject上的组件。
|
||
> AudioEngine是底层实现,提供音频解码、混音、空间化等功能。
|
||
|
||
### 8.1 音频系统
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Audio {
|
||
|
||
// 音频格式
|
||
enum class AudioFormat {
|
||
Unknown,
|
||
WAV,
|
||
OGG,
|
||
MP3,
|
||
FLAC,
|
||
AAC
|
||
};
|
||
|
||
// 音频片段 (资源)
|
||
class AudioClip : public IResource {
|
||
public:
|
||
AudioClip();
|
||
~AudioClip();
|
||
|
||
const String& GetName() const override { return m_name; }
|
||
ResourceType GetType() const override { return ResourceType::Audio; }
|
||
ResourceGUID GetGUID() const override { return m_guid; }
|
||
|
||
bool IsLoaded() const override { return m_loaded; }
|
||
bool IsLoading() const override { return m_loading; }
|
||
float GetLoadingProgress() const override { return m_loadProgress; }
|
||
|
||
const uint8_t* GetData() const { return m_data.get(); }
|
||
size_t GetDataSize() const { return m_dataSize; }
|
||
uint32_t GetSampleRate() const { return m_sampleRate; }
|
||
uint32_t GetChannels() const { return m_channels; }
|
||
uint32_t GetBitsPerSample() const { return m_bitsPerSample; }
|
||
float GetDuration() const { return m_duration; }
|
||
|
||
AudioFormat GetFormat() const { return m_format; }
|
||
|
||
private:
|
||
String m_name;
|
||
ResourceGUID m_guid;
|
||
|
||
std::unique_ptr<uint8_t[]> m_data;
|
||
size_t m_dataSize = 0;
|
||
|
||
uint32_t m_sampleRate = 44100;
|
||
uint32_t m_channels = 2;
|
||
uint32_t m_bitsPerSample = 16;
|
||
float m_duration = 0.0f;
|
||
|
||
AudioFormat m_format = AudioFormat::Unknown;
|
||
|
||
bool m_loaded = false;
|
||
bool m_loading = false;
|
||
float m_loadProgress = 0.0f;
|
||
|
||
friend class AudioEngine;
|
||
};
|
||
|
||
// 音频总线 (混音器)
|
||
class AudioBus {
|
||
public:
|
||
AudioBus(const String& name, AudioBus* parent = nullptr);
|
||
|
||
void SetVolume(float volume);
|
||
float GetVolume() const { return m_volume; }
|
||
|
||
void SetMute(bool mute);
|
||
bool IsMuted() const { return m_muted; }
|
||
|
||
void SetBypassEffects(bool bypass);
|
||
bool IsBypassingEffects() const { return m_bypassEffects; }
|
||
|
||
void AddEffect(AudioEffect* effect);
|
||
void RemoveEffect(AudioEffect* effect);
|
||
|
||
private:
|
||
String m_name;
|
||
AudioBus* m_parent = nullptr;
|
||
std::vector<AudioBus*> m_children;
|
||
std::vector<std::unique_ptr<AudioEffect>> m_effects;
|
||
|
||
float m_volume = 1.0f;
|
||
bool m_muted = false;
|
||
bool m_bypassEffects = false;
|
||
};
|
||
|
||
// 音频引擎 - 底层实现 (不对外直接使用)
|
||
class AudioEngine {
|
||
public:
|
||
static AudioEngine& Get();
|
||
|
||
void Initialize(const AudioEngineConfig& config);
|
||
void Shutdown();
|
||
|
||
const char* GetDeviceName() const;
|
||
uint32_t GetSpeakerCount() const;
|
||
|
||
void Update(float deltaTime);
|
||
|
||
// 资源管理
|
||
std::shared_ptr<AudioClip> LoadClip(const String& filePath);
|
||
void UnloadClip(AudioClip* clip);
|
||
|
||
// 混音器
|
||
AudioBus* GetMasterBus() { return m_masterBus.get(); }
|
||
AudioBus* GetBus(const String& path);
|
||
AudioBus* CreateBus(const String& path);
|
||
|
||
// 内部音频源管理 (由 AudioSystem 使用)
|
||
struct InternalSource {
|
||
uint64_t id = 0;
|
||
void* handle = nullptr; // 底层音频引擎句柄
|
||
};
|
||
|
||
InternalSource CreateInternalSource();
|
||
void DestroyInternalSource(InternalSource source);
|
||
void SetSourceClip(InternalSource source, AudioClip* clip);
|
||
void PlaySource(InternalSource source);
|
||
void StopSource(InternalSource source);
|
||
void PauseSource(InternalSource source);
|
||
void SetSourceVolume(InternalSource source, float volume);
|
||
void SetSourcePitch(InternalSource source, float pitch);
|
||
void SetSourcePosition(InternalSource source, const Vector3& position);
|
||
void SetSourceLoop(InternalSource source, bool loop);
|
||
bool IsSourcePlaying(InternalSource source);
|
||
|
||
// 监听器管理 - Unity 限制只能有一个 AudioListener
|
||
void SetListenerComponent(AudioListenerComponent* listener);
|
||
AudioListenerComponent* GetListenerComponent() const { return m_listenerComponent; }
|
||
|
||
void SetListenerPosition(const Vector3& position);
|
||
void SetListenerVelocity(const Vector3& velocity);
|
||
void SetListenerOrientation(const Vector3& forward, const Vector3& up);
|
||
void SetListenerDopplerFactor(float factor);
|
||
|
||
struct Stats {
|
||
uint32_t activeVoices;
|
||
uint32_t totalVoices;
|
||
uint32_t playingSources;
|
||
uint32_t cpuUsage;
|
||
size_t memoryUsage;
|
||
};
|
||
const Stats& GetStats() const { return m_stats; }
|
||
|
||
private:
|
||
AudioEngine() = default;
|
||
|
||
std::unique_ptr<AudioBus> m_masterBus;
|
||
|
||
std::unordered_map<uint64_t, std::shared_ptr<AudioClip>> m_loadedClips;
|
||
std::vector<InternalSource> m_activeSources;
|
||
uint64_t m_nextSourceId = 1;
|
||
|
||
// 监听器状态
|
||
Vector3 m_listenerPosition;
|
||
Vector3 m_listenerVelocity;
|
||
Vector3 m_listenerForward = Vector3::Forward();
|
||
Vector3 m_listenerUp = Vector3::Up();
|
||
float m_listenerDopplerFactor = 1.0f;
|
||
|
||
// 限制只能有一个 AudioListener
|
||
AudioListenerComponent* m_listenerComponent = nullptr;
|
||
|
||
Stats m_stats;
|
||
|
||
void* m_backend = nullptr; // FMOD / Wwise / OpenAL
|
||
};
|
||
|
||
} // namespace Audio
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十章 动画系统 (Animation)
|
||
|
||
### 10.1 动画系统架构
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Animation {
|
||
|
||
// 动画曲线
|
||
struct AnimationCurve {
|
||
std::vector<Keyframe<float>> floatKeys;
|
||
std::vector<Keyframe<Vector3>> vector3Keys;
|
||
std::vector<Keyframe<Quaternion>> quaternionKeys;
|
||
std::vector<Keyframe<Color>> colorKeys;
|
||
|
||
// 具体类型的求值方法
|
||
float EvaluateFloat(float time, float defaultValue = 0.0f) const;
|
||
Vector3 EvaluateVector3(float time, const Vector3& defaultValue = Vector3::Zero()) const;
|
||
Quaternion EvaluateQuaternion(float time, const Quaternion& defaultValue = Quaternion::Identity()) const;
|
||
Color EvaluateColor(float time, const Color& defaultValue = Color::White) const;
|
||
|
||
// 具体类型的 Key 操作
|
||
void AddKeyFloat(float time, float value);
|
||
void AddKeyVector3(float time, const Vector3& value);
|
||
void AddKeyQuaternion(float time, const Quaternion& value);
|
||
void AddKeyColor(float time, const Color& value);
|
||
|
||
void RemoveKeyFloat(float time);
|
||
void RemoveKeyVector3(float time);
|
||
void RemoveKeyQuaternion(float time);
|
||
void RemoveKeyColor(float time);
|
||
};
|
||
|
||
// 动画片段
|
||
struct AnimationClip : public IResource {
|
||
float duration = 0.0f;
|
||
float sampleRate = 30.0f;
|
||
bool loop = false;
|
||
|
||
// 轨道
|
||
struct Track {
|
||
String path; // 目标路径 e.g., "Root/Child/Arm"
|
||
enum Type { Position, Rotation, Scale, Float, Int, Bool, Trigger } type;
|
||
AnimationCurve curve;
|
||
};
|
||
|
||
std::vector<Track> tracks;
|
||
|
||
// 事件
|
||
struct Event {
|
||
float time;
|
||
String functionName;
|
||
String stringParameter;
|
||
float floatParameter;
|
||
int intParameter;
|
||
};
|
||
std::vector<Event> events;
|
||
};
|
||
|
||
// 骨骼
|
||
struct Bone {
|
||
String name;
|
||
int32 parentIndex = -1;
|
||
Matrix4x4 localMatrix;
|
||
Matrix4x4 worldMatrix;
|
||
Vector3 position;
|
||
Quaternion rotation;
|
||
Vector3 scale;
|
||
};
|
||
|
||
// 骨架
|
||
struct Skeleton : public IResource {
|
||
std::vector<Bone> bones;
|
||
int32 rootBoneIndex = -1;
|
||
|
||
int32 FindBone(const String& name) const;
|
||
const Bone& GetBone(int32 index) const;
|
||
Matrix4x4 GetBoneMatrix(int32 index) const;
|
||
};
|
||
|
||
// 蒙皮数据
|
||
struct SkinningData {
|
||
std::vector<Matrix4x4> bindPoses;
|
||
std::vector<uint32_t> boneIndices;
|
||
std::vector<float> boneWeights;
|
||
};
|
||
|
||
// 动画状态机
|
||
class AnimatorStateMachine {
|
||
public:
|
||
struct State {
|
||
String name;
|
||
AnimationClip* clip = nullptr;
|
||
float speed = 1.0f;
|
||
float cycleOffset = 0.0f;
|
||
|
||
std::vector<Transition> transitions;
|
||
};
|
||
|
||
struct Transition {
|
||
String targetState;
|
||
float exitTime = 0.0f;
|
||
float duration = 0.0f;
|
||
|
||
enum class ConditionMode {
|
||
If,
|
||
IfNot,
|
||
Greater,
|
||
Less,
|
||
Equals
|
||
};
|
||
|
||
struct Condition {
|
||
String parameter;
|
||
ConditionMode mode;
|
||
float threshold;
|
||
};
|
||
std::vector<Condition> conditions;
|
||
};
|
||
|
||
struct Parameter {
|
||
enum Type { Float, Int, Bool, Trigger } type;
|
||
String name;
|
||
};
|
||
|
||
// 状态管理
|
||
void AddState(const String& name);
|
||
void AddTransition(const String& from, const String& to, const Transition& transition);
|
||
void AddParameter(const Parameter& param);
|
||
|
||
// 播放控制
|
||
void Play(const String& stateName);
|
||
void CrossFade(const String& stateName, float duration);
|
||
void Stop();
|
||
|
||
// 参数
|
||
void SetFloat(const String& name, float value);
|
||
void SetInt(const String& name, int32 value);
|
||
void SetBool(const String& name, bool value);
|
||
void SetTrigger(const String& name);
|
||
|
||
float GetFloat(const String& name) const;
|
||
int32 GetInt(const String& name) const;
|
||
bool GetBool(const String& name) const;
|
||
|
||
// 动画层级
|
||
void AddLayer(const String& name, float weight = 1.0f);
|
||
void SetLayerWeight(const String& name, float weight);
|
||
|
||
private:
|
||
std::vector<State> m_states;
|
||
std::vector<Parameter> m_parameters;
|
||
std::unordered_map<String, int32> m_stateIndices;
|
||
|
||
String m_currentState;
|
||
String m_previousState;
|
||
float m_currentTime = 0.0f;
|
||
};
|
||
|
||
// 动画器组件 - 继承Component(类Unity Animator)
|
||
class AnimatorComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
void OnDestroy() override;
|
||
|
||
void SetSkeleton(Skeleton* skeleton);
|
||
Skeleton* GetSkeleton() const { return m_skeleton; }
|
||
|
||
// 播放控制
|
||
void Play(const String& stateName);
|
||
void CrossFade(const String& stateName, float duration);
|
||
void PlayInFixedTime(const String& stateName, float normalizedTime);
|
||
|
||
bool IsPlaying() const;
|
||
float GetCurrentAnimationTime() const;
|
||
float GetCurrentAnimationLength() const;
|
||
|
||
// 层
|
||
void AddLayer(const String& name, float weight);
|
||
void SetLayerWeight(const String& name, float weight);
|
||
|
||
// 参数
|
||
void SetFloat(const String& name, float value);
|
||
void SetInteger(const String& name, int32 value);
|
||
void SetBool(const String& name, bool value);
|
||
void SetTrigger(const String& name);
|
||
|
||
// 根运动
|
||
void SetApplyRootMotion(bool apply) { m_applyRootMotion = apply; }
|
||
bool GetApplyRootMotion() const { return m_applyRootMotion; }
|
||
|
||
Vector3 GetRootPosition() const { return m_rootPosition; }
|
||
Quaternion GetRootRotation() const { return m_rootRotation; }
|
||
|
||
private:
|
||
Skeleton* m_skeleton = nullptr;
|
||
std::unique_ptr<AnimatorStateMachine> m_stateMachine;
|
||
bool m_useGPUAnimation = false;
|
||
Buffer* m_boneMatricesBuffer = nullptr;
|
||
bool m_applyRootMotion = false;
|
||
Vector3 m_rootPosition;
|
||
Quaternion m_rootRotation;
|
||
};
|
||
|
||
// 动画系统管理器 (处理GPU蒙皮、事件等)
|
||
class AnimationSystem {
|
||
public:
|
||
static AnimationSystem& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void Update(float deltaTime);
|
||
|
||
void UpdateGPUBuffers(AnimatorComponent* animator);
|
||
void ProcessAnimationEvents(AnimatorComponent* animator, float prevTime, float currentTime);
|
||
|
||
private:
|
||
void EvaluateState(AnimatorComponent* animator, float time,
|
||
std::vector<Matrix4x4>& boneMatrices);
|
||
void BlendStates(AnimatorComponent* animator, float blendWeight,
|
||
const std::vector<Matrix4x4>& from,
|
||
const std::vector<Matrix4x4>& to,
|
||
std::vector<Matrix4x4>& output);
|
||
};
|
||
|
||
// GPU 蒙皮
|
||
void UpdateGPUBuffers(AnimatorComponent* animator);
|
||
|
||
// 事件触发
|
||
void ProcessAnimationEvents(AnimatorComponent* animator, float prevTime, float currentTime);
|
||
|
||
private:
|
||
void EvaluateState(AnimatorComponent* animator, float time,
|
||
std::vector<Matrix4x4>& boneMatrices);
|
||
void BlendStates(AnimatorComponent* animator, float blendWeight,
|
||
const std::vector<Matrix4x4>& from,
|
||
const std::vector<Matrix4x4>& to,
|
||
std::vector<Matrix4x4>& output);
|
||
};
|
||
|
||
// Blend Shape
|
||
struct BlendShape {
|
||
String name;
|
||
std::vector<Vector3> vertices;
|
||
std::vector<Vector3> normals;
|
||
std::vector<Vector3> tangents;
|
||
};
|
||
|
||
struct BlendShapeFrame {
|
||
float weight = 0.0f;
|
||
std::vector<Vector3> deltaVertices;
|
||
std::vector<Vector3> deltaNormals;
|
||
std::vector<Vector3> deltaTangents;
|
||
};
|
||
|
||
struct BlendShapeData {
|
||
std::vector<BlendShape> shapes;
|
||
std::vector<BlendShapeFrame> frames;
|
||
};
|
||
|
||
// 程序化动画
|
||
namespace ProceduralAnimation {
|
||
|
||
class IKChain {
|
||
public:
|
||
void SetJoints(const std::vector<TransformComponent*>& joints);
|
||
void Solve(const Vector3& target);
|
||
|
||
void SetPoleVector(const Vector3& pole);
|
||
void SetIterations(int32 iterations);
|
||
|
||
private:
|
||
std::vector<TransformComponent*> m_joints;
|
||
Vector3 m_poleVector;
|
||
int32_t m_iterations = 10;
|
||
};
|
||
|
||
class CCDIK : public IKChain {
|
||
public:
|
||
void Solve(const Vector3& target) override;
|
||
};
|
||
|
||
class FABRIK : public IKChain {
|
||
public:
|
||
void Solve(const Vector3& target) override;
|
||
|
||
private:
|
||
void ForwardReach(const Vector3& target);
|
||
void BackwardReach(const Vector3& base);
|
||
void SolveConstraints();
|
||
};
|
||
|
||
} // namespace ProceduralAnimation
|
||
} // namespace Animation
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十一章 粒子系统 (Particle System)
|
||
|
||
### 11.1 粒子系统架构
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Particles {
|
||
|
||
// 粒子数据 - 粒子系统使用SoA布局以优化SIMD性能(这是性能关键路径的例外)
|
||
struct Particle {
|
||
Vector3 position;
|
||
Vector3 velocity;
|
||
Vector3 acceleration;
|
||
|
||
Quaternion rotation;
|
||
float rotationSpeed;
|
||
|
||
float size;
|
||
float lifetime;
|
||
float age;
|
||
|
||
Color color;
|
||
float alpha;
|
||
|
||
uint32_t seed;
|
||
bool alive;
|
||
};
|
||
|
||
// 粒子发射器
|
||
class ParticleEmitter {
|
||
public:
|
||
// 发射模式
|
||
enum class EmitMode {
|
||
Continuous,
|
||
Burst,
|
||
Distance
|
||
};
|
||
|
||
// 形状
|
||
enum class ShapeType {
|
||
Sphere,
|
||
Box,
|
||
Cone,
|
||
Circle,
|
||
Edge,
|
||
MeshSurface,
|
||
MeshVolume
|
||
};
|
||
|
||
// 发射参数
|
||
float rate = 10.0f;
|
||
int maxParticles = 1000;
|
||
float lifetime = 5.0f;
|
||
|
||
// 初始速度
|
||
Vector3 velocityMin = Vector3(-1, 1, -1);
|
||
Vector3 velocityMax = Vector3(1, 1, 1);
|
||
float speedMin = 1.0f;
|
||
float speedMax = 5.0f;
|
||
|
||
// 初始变换
|
||
float startSizeMin = 0.1f;
|
||
float startSizeMax = 0.5f;
|
||
float startRotationMin = 0.0f;
|
||
float startRotationMax = 360.0f;
|
||
Color startColor = Color::White;
|
||
|
||
// 形状
|
||
ShapeType shape = ShapeType::Sphere;
|
||
float shapeRadius = 1.0f;
|
||
float shapeAngle = 25.0f;
|
||
Vector3 shapeBoxSize = Vector3::One();
|
||
|
||
// 发射
|
||
EmitMode emitMode = EmitMode::Continuous;
|
||
int burstCount = 10;
|
||
float burstInterval = 1.0f;
|
||
};
|
||
|
||
// 粒子系统组件 - 继承Component(类Unity ParticleSystem)
|
||
class ParticleSystemComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
void OnDestroy() override;
|
||
|
||
// 播放控制(Unity 风格)
|
||
void Play();
|
||
void Stop();
|
||
void Pause();
|
||
void Resume();
|
||
void Clear();
|
||
|
||
bool IsPlaying() const { return m_isPlaying && !m_isPaused; }
|
||
bool IsPaused() const { return m_isPaused; }
|
||
bool IsStopped() const { return !m_isPlaying; }
|
||
|
||
void SetLoop(bool loop) { m_loop = loop; }
|
||
bool GetLoop() const { return m_loop; }
|
||
|
||
void SetEmitRate(float rate) { m_emitter.rate = rate; }
|
||
float GetEmitRate() const { return m_emitter.rate; }
|
||
|
||
void SetLifetime(float lifetime) { m_emitter.lifetime = lifetime; }
|
||
float GetLifetime() const { return m_emitter.lifetime; }
|
||
|
||
void SetStartSpeed(float speed) { m_emitter.speedMin = m_emitter.speedMax = speed; }
|
||
float GetStartSpeed() const { return m_emitter.speedMin; }
|
||
|
||
void SetStartSize(float size) { m_emitter.startSizeMin = m_emitter.startSizeMax = size; }
|
||
float GetStartSize() const { return m_emitter.startSizeMin; }
|
||
|
||
void SetStartColor(const Color& color) { m_emitter.startColor = color; }
|
||
Color GetStartColor() const { return m_emitter.startColor; }
|
||
|
||
private:
|
||
ParticleEmitter m_emitter;
|
||
bool m_isPlaying = false;
|
||
bool m_isPaused = false;
|
||
bool m_loop = true;
|
||
float m_simulationSpeed = 1.0f;
|
||
float m_startDelay = 0.0f;
|
||
uint32_t m_randomSeed = 0;
|
||
};
|
||
|
||
// GPU 粒子系统
|
||
class GPUParticleSystem {
|
||
public:
|
||
void Initialize(uint32_t maxParticles);
|
||
void Shutdown();
|
||
|
||
void Update(float deltaTime, const ParticleSystemComponent& config);
|
||
void Render(RenderContext& context);
|
||
|
||
// GPU 缓冲区
|
||
Buffer* GetPositionBuffer() { return m_positionBuffer.get(); }
|
||
Buffer* GetVelocityBuffer() { return m_velocityBuffer.get(); }
|
||
Buffer* GetColorBuffer() { return m_colorBuffer.get(); }
|
||
|
||
private:
|
||
struct GPUParticle {
|
||
Vector4 position; // w = size
|
||
Vector4 velocity; // w = lifetime
|
||
Vector4 color; // w = rotation
|
||
};
|
||
|
||
uint32_t m_maxParticles = 0;
|
||
|
||
std::unique_ptr<Buffer> m_positionBuffer;
|
||
std::unique_ptr<Buffer> m_velocityBuffer;
|
||
std::unique_ptr<Buffer> m_colorBuffer;
|
||
std::unique_ptr<Buffer> m_indexBuffer;
|
||
|
||
ComputePipeline m_updatePipeline;
|
||
};
|
||
|
||
// 粒子系统管理器
|
||
class ParticleSystemManager {
|
||
public:
|
||
static ParticleSystemManager& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void Update(float deltaTime);
|
||
void Render(RenderContext& context);
|
||
|
||
// 发射器
|
||
ParticleEmitter* CreateEmitter();
|
||
void DestroyEmitter(ParticleEmitter* emitter);
|
||
|
||
// GPU 粒子
|
||
GPUParticleSystem* GetGPUParticleSystem() { return &m_gpuSystem; }
|
||
|
||
private:
|
||
std::vector<std::unique_ptr<ParticleEmitter>> m_emitters;
|
||
GPUParticleSystem m_gpuSystem;
|
||
};
|
||
|
||
// VFX Graph 集成
|
||
namespace VFXGraph {
|
||
|
||
class VFXGraphAsset : public IResource {
|
||
public:
|
||
// VFX Graph 描述
|
||
};
|
||
|
||
class VFXGraphComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
VFXGraphAsset* asset = nullptr;
|
||
|
||
std::unordered_map<String, float> floatParameters;
|
||
std::unordered_map<String, Vector3> vector3Parameters;
|
||
std::unordered_map<String, Color> colorParameters;
|
||
std::unordered_map<String, bool> boolParameters;
|
||
|
||
void SetFloat(const String& name, float value);
|
||
void SetVector3(const String& name, const Vector3& value);
|
||
void SetColor(const String& name, const Color& value);
|
||
void SetBool(const String& name, bool value);
|
||
|
||
void Play();
|
||
void Stop();
|
||
void Pause();
|
||
void SetSeed(uint32_t seed);
|
||
};
|
||
|
||
} // namespace VFXGraph
|
||
} // namespace Particles
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十二章 网络系统 (Networking)
|
||
|
||
### 12.1 网络系统架构
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Networking {
|
||
|
||
// 网络模式
|
||
enum class NetworkMode {
|
||
Offline,
|
||
Host,
|
||
Client,
|
||
Server
|
||
};
|
||
|
||
// 传输层
|
||
enum class TransportProtocol {
|
||
UDP,
|
||
TCP,
|
||
WebSocket
|
||
};
|
||
|
||
// 网络消息
|
||
struct NetworkMessage {
|
||
uint32_t type;
|
||
uint32_t channel;
|
||
uint32_t senderId;
|
||
uint64_t sequence;
|
||
uint64_t timestamp;
|
||
std::vector<uint8_t> data;
|
||
};
|
||
|
||
// 消息类型
|
||
enum class MessageType : uint32_t {
|
||
// 内置
|
||
Connect = 1,
|
||
Disconnect = 2,
|
||
Heartbeat = 3,
|
||
Ack = 4,
|
||
|
||
// 游戏
|
||
Spawn = 100,
|
||
Despawn = 101,
|
||
TransformUpdate = 102,
|
||
ComponentUpdate = 103,
|
||
RPC = 104,
|
||
SceneChange = 105,
|
||
};
|
||
|
||
// 网络通道
|
||
enum class NetworkChannel {
|
||
Reliable,
|
||
Unreliable,
|
||
Voice,
|
||
Raw
|
||
};
|
||
|
||
// 网络连接
|
||
class NetworkConnection {
|
||
public:
|
||
uint32_t GetId() const { return m_id; }
|
||
const String& GetAddress() const { return m_address; }
|
||
float GetRoundTripTime() const { return m_rtt; }
|
||
|
||
bool IsConnected() const { return m_connected; }
|
||
|
||
void Send(uint32_t type, const void* data, size_t size, NetworkChannel channel);
|
||
void Disconnect();
|
||
|
||
private:
|
||
uint32_t m_id = 0;
|
||
String m_address;
|
||
bool m_connected = false;
|
||
float m_rtt = 0.0f;
|
||
};
|
||
|
||
// 网络玩家
|
||
struct NetworkPlayer {
|
||
uint32_t id;
|
||
String name;
|
||
NetworkConnection* connection = nullptr;
|
||
GameObject* avatar = nullptr;
|
||
bool isLocal = false;
|
||
bool isReady = false;
|
||
};
|
||
|
||
// 网络管理器
|
||
class NetworkManager {
|
||
public:
|
||
static NetworkManager& Get();
|
||
|
||
void Initialize(const NetworkConfig& config);
|
||
void Shutdown();
|
||
|
||
// 模式
|
||
NetworkMode GetMode() const { return m_mode; }
|
||
|
||
// 主机
|
||
bool StartHost(uint16_t port);
|
||
void StopHost();
|
||
|
||
// 客户端
|
||
bool Connect(const String& address, uint16_t port);
|
||
void Disconnect();
|
||
|
||
// 玩家
|
||
uint32_t GetLocalPlayerId() const { return m_localPlayerId; }
|
||
NetworkPlayer* GetPlayer(uint32_t id);
|
||
const std::vector<NetworkPlayer*>& GetPlayers();
|
||
|
||
// 消息
|
||
void Send(uint32_t playerId, uint32_t type, const void* data, size_t size,
|
||
NetworkChannel channel = NetworkChannel::Reliable);
|
||
void SendToAll(uint32_t type, const void* data, size_t size,
|
||
NetworkChannel channel = NetworkChannel::Reliable);
|
||
|
||
// RPC
|
||
template<typename T>
|
||
void RegisterRPC(const String& name, T* obj, void (T::*func)(NetworkReader&));
|
||
|
||
// 场景同步
|
||
void SetNetworkedScene(Scene* scene);
|
||
void AddNetworkedObject(GameObject* gameObject);
|
||
void RemoveNetworkedObject(GameObject* gameObject);
|
||
|
||
// 同步
|
||
void Update(float deltaTime);
|
||
|
||
// 事件
|
||
Event<uint32_t> OnPlayerConnected;
|
||
Event<uint32_t> OnPlayerDisconnected;
|
||
Event<NetworkMessage&> OnMessageReceived;
|
||
|
||
private:
|
||
NetworkMode m_mode = NetworkMode::Offline;
|
||
uint32_t m_localPlayerId = 0;
|
||
std::vector<NetworkPlayer> m_players;
|
||
|
||
void* m_transport = nullptr; // ENet / LiteNetLib / custom
|
||
};
|
||
|
||
// 网络组件
|
||
class NetworkIdentityComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
uint32_t networkId = 0;
|
||
bool isLocalPlayer = false;
|
||
bool isOwnedByClient = false;
|
||
bool canSpawn = true;
|
||
bool syncTransform = true;
|
||
bool syncComponents = true;
|
||
};
|
||
|
||
class NetworkTransformComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class SyncMode {
|
||
None,
|
||
SyncTransform,
|
||
SyncPosition,
|
||
SyncPositionAndRotation,
|
||
SyncPositionRotationScale
|
||
};
|
||
|
||
SyncMode syncMode = SyncMode::SyncPositionRotationScale;
|
||
float snapThreshold = 0.5f;
|
||
float interpolationDelay = 0.1f;
|
||
|
||
float syncInterval = 0.05f;
|
||
|
||
bool enablePrediction = true;
|
||
float predictionTime = 0.1f;
|
||
|
||
bool quantizePosition = true;
|
||
int positionPrecision = 0.01f;
|
||
bool quantizeRotation = true;
|
||
int rotationPrecision = 1;
|
||
};
|
||
|
||
// 远程过程调用
|
||
namespace RPC {
|
||
|
||
// RPC 属性
|
||
enum class RpcTarget {
|
||
Server,
|
||
Others,
|
||
All,
|
||
Specific
|
||
};
|
||
|
||
enum class RpcMode {
|
||
Normal,
|
||
Buffered,
|
||
Unbuffered
|
||
};
|
||
|
||
// RPC 调用
|
||
struct RpcCall {
|
||
String methodName;
|
||
std::vector<uint8_t> args;
|
||
RpcTarget target;
|
||
uint32_t targetPlayer;
|
||
float timestamp;
|
||
};
|
||
|
||
// 注册 RPC
|
||
#define XE_RPC(methodName, target) \
|
||
void methodName(NetworkReader& reader); \
|
||
static void _RPC_##methodName(NetworkIdentityComponent* identity, NetworkReader& reader) { \
|
||
auto* comp = identity->GetComponent<NetworkIdentityComponent>(); \
|
||
if (comp && comp->isOwnedByClient) { \
|
||
auto* obj = static_cast<MyClass*>(identity); \
|
||
obj->methodName(reader); \
|
||
} \
|
||
}
|
||
|
||
// 服务器/客户端 RPC
|
||
class RpcHandler {
|
||
public:
|
||
void Register(uint32_t hash, std::function<void(NetworkIdentityComponent*, NetworkReader&)> handler);
|
||
void Call(NetworkIdentityComponent* identity, uint32_t methodHash, NetworkWriter& writer,
|
||
RpcTarget target, uint32_t targetPlayer = 0);
|
||
void Handle(NetworkMessage& msg);
|
||
};
|
||
|
||
} // namespace RPC
|
||
|
||
// 网络序列化
|
||
class NetworkSerializer {
|
||
public:
|
||
void Serialize(NetworkWriter& writer, const GameObject& gameObject);
|
||
void Deserialize(NetworkReader& reader, GameObject& gameObject);
|
||
|
||
void SerializeTransform(NetworkWriter& writer, const TransformComponent& transform);
|
||
void DeserializeTransform(NetworkReader& reader, TransformComponent& transform);
|
||
|
||
// 组件同步
|
||
void SerializeComponent(NetworkWriter& writer, uint32_t componentTypeId, const void* component);
|
||
void* DeserializeComponent(NetworkReader& reader, uint32_t componentTypeId, GameObject* gameObject);
|
||
};
|
||
|
||
// 网络预测
|
||
class ClientPrediction {
|
||
public:
|
||
struct PredictedState {
|
||
Vector3 position;
|
||
Quaternion rotation;
|
||
Vector3 velocity;
|
||
float timestamp;
|
||
};
|
||
|
||
void StorePredictedState(const Vector3& position, const Quaternion& rotation,
|
||
const Vector3& velocity);
|
||
void ApplyServerCorrection(const Vector3& serverPosition, const Quaternion& serverRotation);
|
||
|
||
bool HasPredictionError() const;
|
||
void Reconcile();
|
||
|
||
private:
|
||
std::deque<PredictedState> m_predictedStates;
|
||
std::deque<PredictedState> m_unconfirmedStates;
|
||
|
||
Vector3 m_lastServerPosition;
|
||
Quaternion m_lastServerRotation;
|
||
};
|
||
|
||
// 延迟补偿
|
||
class LagCompensation {
|
||
public:
|
||
struct ServerFrame {
|
||
float timestamp;
|
||
std::vector<EntitySnapshot> entities;
|
||
};
|
||
|
||
void RecordFrame(const std::vector<EntitySnapshot>& entities);
|
||
EntitySnapshot GetInterpolatedSnapshot(float timestamp);
|
||
|
||
bool Raycast(Ray& ray, float maxDistance, RaycastHit& hit);
|
||
|
||
private:
|
||
std::deque<ServerFrame> m_frames;
|
||
float m_recordDuration = 1.0f; // 记录1秒
|
||
};
|
||
|
||
} // namespace Networking
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十三章 UI 系统 (In-Game UI / UGUI)
|
||
|
||
> **架构说明**: Unity UGUI风格的UI系统。UI元素作为组件挂载在GameObject上。
|
||
> 每个UI元素GameObject必须挂载RectTransform组件。
|
||
|
||
### 13.1 UI 系统架构
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace UI {
|
||
|
||
// ============================================================================
|
||
// UI 组件 (Unity UGUI风格)
|
||
// ============================================================================
|
||
|
||
// 矩形变换组件 (Unity RectTransform,继承 Transform)
|
||
class RectTransformComponent : public TransformComponent {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
// 锚点
|
||
Vector2 anchorMin = Vector2(0, 0);
|
||
Vector2 anchorMax = Vector2(0, 0);
|
||
Vector2 pivot = Vector2(0.5f, 0.5f);
|
||
|
||
// 位置和大小
|
||
Vector2 anchoredPosition = Vector2::Zero();
|
||
Vector2 sizeDelta = Vector2(100, 100);
|
||
|
||
// 偏移 (相对于锚点)
|
||
Vector2 offsetMin = Vector2::Zero();
|
||
Vector2 offsetMax = Vector2::Zero();
|
||
|
||
// 计算属性
|
||
Vector3 GetWorldPosition() const;
|
||
Vector2 GetWorldSize() const;
|
||
void SetSize(const Vector2& size);
|
||
|
||
private:
|
||
// 父子层级由基类 TransformComponent 管理
|
||
mutable Matrix4x4 m_worldMatrix;
|
||
mutable bool m_dirty = true;
|
||
};
|
||
|
||
// 图像组件 (Unity Image)
|
||
class ImageComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
ResourceGUID spriteGuid;
|
||
|
||
enum class Type {
|
||
Simple,
|
||
Sliced,
|
||
Tiled,
|
||
Filled
|
||
};
|
||
Type type = Type::Simple;
|
||
|
||
float fillAmount = 1.0f;
|
||
enum class FillMethod { Horizontal, Vertical, Radial90, Radial180, Radial360 };
|
||
FillMethod fillMethod = FillMethod::Horizontal;
|
||
bool fillClockwise = true;
|
||
int fillOrigin = 0;
|
||
|
||
Color color = Color::White;
|
||
bool raycastTarget = true;
|
||
|
||
Event<> OnSpriteChanged;
|
||
};
|
||
|
||
// 文本组件 (Unity Text / TextMeshPro)
|
||
class TextComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
String text;
|
||
ResourceGUID fontGuid;
|
||
|
||
int fontSize = 14;
|
||
enum class FontStyle { Normal, Bold, Italic, BoldAndItalic };
|
||
FontStyle fontStyle = FontStyle::Normal;
|
||
|
||
Color color = Color::White;
|
||
Color outlineColor = Color::Black;
|
||
float outlineWidth = 0.0f;
|
||
|
||
enum class Alignment {
|
||
UpperLeft, UpperCenter, UpperRight,
|
||
MiddleLeft, MiddleCenter, MiddleRight,
|
||
LowerLeft, LowerCenter, LowerRight
|
||
};
|
||
Alignment alignment = Alignment::MiddleCenter;
|
||
|
||
float lineSpacing = 1.0f;
|
||
bool richText = true;
|
||
bool horizontalOverflow = false;
|
||
bool verticalOverflow = true;
|
||
bool raycastTarget = true;
|
||
};
|
||
|
||
// 按钮组件 (Unity Button)
|
||
class ButtonComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class Transition {
|
||
None,
|
||
ColorTint,
|
||
SpriteSwap,
|
||
Animation
|
||
};
|
||
Transition transition = Transition::ColorTint;
|
||
|
||
// 颜色状态
|
||
Color normalColor = Color::White;
|
||
Color highlightedColor = Color(1, 1, 1, 0.8f);
|
||
Color pressedColor = Color(1, 1, 1, 0.6f);
|
||
Color disabledColor = Color(1, 1, 1, 0.5f);
|
||
|
||
// 精灵状态
|
||
ResourceGUID normalSpriteGuid;
|
||
ResourceGUID highlightedSpriteGuid;
|
||
ResourceGUID pressedSpriteGuid;
|
||
ResourceGUID disabledSpriteGuid;
|
||
|
||
// 事件
|
||
Event<> OnClick;
|
||
Event<> OnPointerDown;
|
||
Event<> OnPointerUp;
|
||
Event<> OnPointerEnter;
|
||
Event<> OnPointerExit;
|
||
};
|
||
|
||
// 输入字段组件 (Unity InputField / TMP_InputField)
|
||
class InputFieldComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
String text;
|
||
String placeholder;
|
||
|
||
int characterLimit = 0;
|
||
bool multiLine = false;
|
||
bool isPassword = false;
|
||
char passwordChar = '*';
|
||
|
||
enum class ContentType {
|
||
Standard,
|
||
Autocorrected,
|
||
DecimalNumber,
|
||
IntegerNumber,
|
||
Name,
|
||
EmailAddress,
|
||
Password,
|
||
PIN,
|
||
MobileTelephoneNumber,
|
||
TelephoneNumber,
|
||
URL,
|
||
Alphabet
|
||
};
|
||
ContentType contentType = ContentType::Standard;
|
||
|
||
Color color = Color::White;
|
||
bool raycastTarget = true;
|
||
|
||
// 事件
|
||
Event<String> OnValueChanged;
|
||
Event<String> OnEndEdit;
|
||
Event<> OnSubmit;
|
||
};
|
||
|
||
// 滑动条组件 (Unity Slider)
|
||
class SliderComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
float value = 0.5f;
|
||
float minValue = 0.0f;
|
||
float maxValue = 1.0f;
|
||
bool wholeNumbers = false;
|
||
|
||
enum class Direction {
|
||
LeftToRight,
|
||
RightToLeft,
|
||
BottomToTop,
|
||
TopToBottom
|
||
};
|
||
Direction direction = Direction::LeftToRight;
|
||
|
||
Color color = Color::White;
|
||
bool raycastTarget = true;
|
||
|
||
// 事件
|
||
Event<float> OnValueChanged;
|
||
Event<float> OnPointerDown;
|
||
Event<float> OnPointerUp;
|
||
};
|
||
|
||
// 滚动视图组件 (Unity ScrollRect)
|
||
class ScrollViewComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
GameObject* contentGameObject = nullptr;
|
||
|
||
enum class MovementType {
|
||
Elastic,
|
||
Clamped,
|
||
Unrestricted
|
||
};
|
||
MovementType movementType = MovementType::Elastic;
|
||
|
||
float elasticity = 0.1f;
|
||
float decelerationRate = 0.135f;
|
||
|
||
GameObject* horizontalScrollbar = nullptr;
|
||
GameObject* verticalScrollbar = nullptr;
|
||
|
||
bool enabled = true;
|
||
bool raycastTarget = true;
|
||
};
|
||
|
||
// 画布组件 (Unity Canvas)
|
||
class CanvasComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class RenderMode {
|
||
ScreenSpaceOverlay,
|
||
ScreenSpaceCamera,
|
||
WorldSpace
|
||
};
|
||
RenderMode renderMode = RenderMode::ScreenSpaceOverlay;
|
||
|
||
GameObject* targetCamera = nullptr;
|
||
float planeDistance = 100.0f;
|
||
|
||
float scaleFactor = 1.0f;
|
||
|
||
int32_t renderOrder = 0;
|
||
};
|
||
|
||
// 画布缩放器组件 (Unity CanvasScaler)
|
||
class CanvasScalerComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class ScaleMode {
|
||
ConstantPixelSize,
|
||
ScaleWithScreenSize,
|
||
ConstantPhysicalSize
|
||
};
|
||
ScaleMode uiScaleMode = ScaleMode::ScaleWithScreenSize;
|
||
|
||
Vector2 referenceResolution = Vector2(800, 600);
|
||
float referencePixelsPerUnit = 100.0f;
|
||
|
||
enum class ScreenMatchMode {
|
||
Width,
|
||
Height,
|
||
Expand,
|
||
Shrink
|
||
};
|
||
ScreenMatchMode screenMatchMode = ScreenMatchMode::Expand;
|
||
|
||
float matchWidthOrHeight = 0.0f;
|
||
};
|
||
|
||
// 布局元素组件 (用于布局组)
|
||
class LayoutElementComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
float minWidth = 0.0f;
|
||
float minHeight = 0.0f;
|
||
float preferredWidth = 0.0f;
|
||
float preferredHeight = 0.0f;
|
||
float flexibleWidth = 0.0f;
|
||
float flexibleHeight = 0.0f;
|
||
int32_t layoutPriority = 0;
|
||
};
|
||
|
||
// 水平布局组组件 (Unity HorizontalLayoutGroupComponent)
|
||
class HorizontalLayoutGroupComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
float spacing = 0.0f;
|
||
bool childForceExpandWidth = true;
|
||
bool childForceExpandHeight = false;
|
||
bool childControlWidth = true;
|
||
bool childControlHeight = true;
|
||
int32_t childAlignment = 4;
|
||
};
|
||
|
||
// 垂直布局组组件 (Unity VerticalLayoutGroupComponent)
|
||
class VerticalLayoutGroupComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
float spacing = 0.0f;
|
||
bool childForceExpandWidth = false;
|
||
bool childForceExpandHeight = true;
|
||
bool childControlWidth = true;
|
||
bool childControlHeight = true;
|
||
int32_t childAlignment = 4;
|
||
};
|
||
|
||
// 网格布局组组件 (Unity GridLayoutGroupComponent)
|
||
class GridLayoutGroupComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
Vector2 cellSize = Vector2(100, 100);
|
||
Vector2 spacing = Vector2::Zero();
|
||
int32_t startCorner = 0;
|
||
int32_t startAxis = 0;
|
||
int32_t constraint = 0;
|
||
int32_t constraintCount = 2;
|
||
};
|
||
|
||
// ============================================================================
|
||
// UI 系统 (处理布局、事件等 - 传统Unity风格)
|
||
// ============================================================================
|
||
|
||
class UISystem {
|
||
public:
|
||
void Initialize();
|
||
void Shutdown();
|
||
void Update(float deltaTime);
|
||
|
||
// 射线检测
|
||
GameObject* Raycast(const Vector2& screenPosition);
|
||
std::vector<GameObject*> RaycastAll(const Vector2& screenPosition);
|
||
|
||
// 焦点管理
|
||
void SetFocus(GameObject* element);
|
||
GameObject* GetFocusedElement();
|
||
void ClearFocus();
|
||
|
||
private:
|
||
void ProcessLayoutGroups();
|
||
void ProcessRaycasts();
|
||
void ProcessEvents();
|
||
|
||
GameObject* m_focusedElement = nullptr;
|
||
GameObject* m_hoveredElement = nullptr;
|
||
};
|
||
|
||
// ============================================================================
|
||
// UI 渲染器 (底层实现)
|
||
// ============================================================================
|
||
|
||
class UIRenderer {
|
||
public:
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void Render(Scene& scene);
|
||
|
||
// 批处理
|
||
void BeginBatch();
|
||
void AddToBatch(GameObject* gameObject, const Matrix4x4& transform, const Mesh* mesh, const Material* material);
|
||
void EndBatch();
|
||
|
||
// 默认材质
|
||
Material* defaultMaterial = nullptr;
|
||
Material* defaultSpriteMaterial = nullptr;
|
||
};
|
||
|
||
// ============================================================================
|
||
// 画布渲染器组件 (挂载在 Canvas 上)
|
||
class CanvasRendererComponent : public Component {
|
||
public:
|
||
void Update(float deltaTime) override;
|
||
|
||
bool renderMode = true;
|
||
uint32_t vertexCount = 0;
|
||
uint32_t indexCount = 0;
|
||
bool hasPopulateMesh = false;
|
||
|
||
std::function<void(Mesh*)> onPopulateMesh;
|
||
};
|
||
|
||
// ============================================================================
|
||
// UI 事件系统
|
||
// ============================================================================
|
||
|
||
class UIEventSystem {
|
||
public:
|
||
static UIEventSystem& Get();
|
||
|
||
// 指针事件
|
||
void OnPointerDown(PointerEvent& event);
|
||
void OnPointerUp(PointerEvent& event);
|
||
void OnPointerMove(PointerEvent& event);
|
||
void OnPointerClick(PointerEvent& event);
|
||
|
||
// 键盘事件
|
||
void OnKeyDown(KeyEvent& event);
|
||
void OnKeyUp(KeyEvent& event);
|
||
void OnTextInput(TextInputEvent& event);
|
||
|
||
// 拖放事件
|
||
void OnDragStart(DragEvent& event);
|
||
void OnDrag(DragEvent& event);
|
||
void OnDragEnd(DragEvent& event);
|
||
|
||
private:
|
||
GameObject* m_currentPointerOver = nullptr;
|
||
GameObject* m_draggedElement = nullptr;
|
||
GameObject* m_focusedElement = nullptr;
|
||
};
|
||
|
||
} // namespace UI
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十四章 编辑器架构 (Editor)
|
||
|
||
### 14.1 编辑器整体架构
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Editor {
|
||
|
||
// 编辑器应用
|
||
class EditorApplication {
|
||
public:
|
||
static EditorApplication& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
void Run();
|
||
|
||
// 主循环
|
||
void Update();
|
||
void Render();
|
||
|
||
// 项目
|
||
Project* GetCurrentProject() { return m_currentProject.get(); }
|
||
void NewProject(const String& path);
|
||
void OpenProject(const String& path);
|
||
void SaveProject();
|
||
void CloseProject();
|
||
|
||
// 编辑器状态
|
||
enum class Mode {
|
||
Stopped,
|
||
Playing,
|
||
Paused,
|
||
Step
|
||
};
|
||
Mode GetMode() const { return m_mode; }
|
||
void Play();
|
||
void Pause();
|
||
void Stop();
|
||
void Step();
|
||
|
||
// 场景操作
|
||
void NewScene();
|
||
void OpenScene(const String& path);
|
||
void SaveScene();
|
||
void SaveSceneAs(const String& path);
|
||
|
||
// 窗口
|
||
void RegisterWindow(EditorWindow* window);
|
||
void UnregisterWindow(EditorWindow* window);
|
||
|
||
private:
|
||
std::unique_ptr<Project> m_currentProject;
|
||
Mode m_mode = Mode::Stopped;
|
||
std::vector<std::unique_ptr<EditorWindow>> m_windows;
|
||
};
|
||
|
||
// 编辑器窗口基类
|
||
class EditorWindow {
|
||
public:
|
||
virtual ~EditorWindow() = default;
|
||
|
||
virtual void OnOpen() {}
|
||
virtual void OnClose() {}
|
||
virtual void Update(float deltaTime) {}
|
||
virtual void OnGUI() {}
|
||
|
||
virtual bool IsOpen() const { return m_open; }
|
||
void SetOpen(bool open) { m_open = open; }
|
||
|
||
virtual ImVec2 GetSize() const { return ImVec2(400, 300); }
|
||
virtual ImVec2 GetPosition() const { return ImVec2(0, 0); }
|
||
|
||
protected:
|
||
String m_title;
|
||
bool m_open = true;
|
||
};
|
||
|
||
// 项目
|
||
class Project {
|
||
public:
|
||
String name;
|
||
String path;
|
||
String assemblyName;
|
||
|
||
// 设置
|
||
ProjectSettings settings;
|
||
|
||
// 资源(使用编辑器专用的资源数据库)
|
||
EditorAssetDatabase* GetAssetDatabase() { return m_assetDatabase.get(); }
|
||
|
||
// 场景
|
||
std::vector<String> GetScenes();
|
||
void AddScene(const String& scenePath);
|
||
void RemoveScene(const String& scenePath);
|
||
|
||
// 构建
|
||
void Build(const BuildSettings& settings);
|
||
|
||
private:
|
||
std::unique_ptr<EditorAssetDatabase> m_assetDatabase;
|
||
std::vector<String> m_scenes;
|
||
};
|
||
|
||
// 编辑器资源数据库(继承自 Resources::AssetDatabase)
|
||
class EditorAssetDatabase {
|
||
public:
|
||
void Initialize(const String& projectPath);
|
||
void Shutdown();
|
||
|
||
// 资源查找
|
||
Resources::ResourceGUID FindAsset(const String& guid) const;
|
||
Resources::ResourceGUID FindAssetByPath(const String& path) const;
|
||
String GetAssetPath(const Resources::ResourceGUID& guid) const;
|
||
|
||
// 资源操作
|
||
void ImportAsset(const String& sourcePath);
|
||
void ReimportAsset(const Resources::ResourceGUID& guid);
|
||
void DeleteAsset(const Resources::ResourceGUID& guid);
|
||
|
||
// 刷新
|
||
void Refresh();
|
||
|
||
// GUID 生成
|
||
Resources::ResourceGUID GenerateGUID();
|
||
|
||
// 编辑器特定功能
|
||
void SelectAsset(const Resources::ResourceGUID& guid);
|
||
std::vector<Resources::ResourceGUID> GetSelectedAssets() const;
|
||
void OpenInExternalEditor(const Resources::ResourceGUID& guid);
|
||
|
||
// 资源变换监听
|
||
Core::Event<const String&> OnAssetRenamed;
|
||
Core::Event<const Resources::ResourceGUID&> OnAssetDeleted;
|
||
|
||
private:
|
||
void ScanDirectory(const String& dirPath);
|
||
void ImportAssetInternal(const String& sourcePath, const String& destPath);
|
||
|
||
struct AssetMetadata {
|
||
Resources::ResourceGUID guid;
|
||
String path;
|
||
String extension;
|
||
int64_t fileSize;
|
||
int64_t lastModified;
|
||
String importerType;
|
||
JsonObject metadata;
|
||
};
|
||
|
||
std::unordered_map<String, AssetMetadata> m_guidToAsset;
|
||
std::unordered_map<String, Resources::ResourceGUID> m_pathToGuid;
|
||
|
||
std::vector<Resources::ResourceGUID> m_selectedAssets;
|
||
};
|
||
|
||
// 资源导入器
|
||
class AssetImporter {
|
||
public:
|
||
virtual ~AssetImporter() = default;
|
||
|
||
virtual bool CanImport(const String& extension) const = 0;
|
||
virtual void Import(const String& sourcePath, const ResourceGUID& guid,
|
||
const ImportSettings& settings) = 0;
|
||
virtual ImportSettings* GetDefaultSettings() const = 0;
|
||
|
||
protected:
|
||
String GetOutputPath(const String& sourcePath, const ResourceGUID& guid);
|
||
};
|
||
|
||
// 具体导入器
|
||
class TextureImporter : public AssetImporter {
|
||
public:
|
||
bool CanImport(const String& extension) const override;
|
||
void Import(const String& sourcePath, const ResourceGUID& guid,
|
||
const ImportSettings& settings) override;
|
||
|
||
struct Settings : ImportSettings {
|
||
TextureType textureType = TextureType::Texture2D;
|
||
int maxSize = 2048;
|
||
TextureFormat format = TextureFormat::RGBA;
|
||
bool generateMipmaps = true;
|
||
bool sRGB = true;
|
||
FilterMode filterMode = FilterMode::Bilinear;
|
||
WrapMode wrapMode = WrapMode::Repeat;
|
||
};
|
||
};
|
||
|
||
class MeshImporter : public AssetImporter {
|
||
public:
|
||
bool CanImport(const String& extension) const override;
|
||
void Import(const String& sourcePath, const ResourceGUID& guid,
|
||
const ImportSettings& settings) override;
|
||
};
|
||
|
||
class MaterialImporter : public AssetImporter {
|
||
public:
|
||
bool CanImport(const String& extension) const override;
|
||
void Import(const String& sourcePath, const ResourceGUID& guid,
|
||
const ImportSettings& settings) override;
|
||
};
|
||
|
||
// 编辑器场景管理 (Unity Editor 风格)
|
||
//
|
||
// 编辑器/运行时模式切换机制:
|
||
// - Stop (编辑模式): 编辑器直接操作 m_editingScene
|
||
// - Play (运行模式):
|
||
// 1. 深拷贝 m_editingScene -> m_runtimeScene (包括所有Entity和Component)
|
||
// 2. 运行 m_runtimeScene
|
||
// 3. 用户在运行时对Scene的修改都在 m_runtimeScene 中
|
||
// - Stop -> Play 循环:
|
||
// 1. 销毁旧的 m_runtimeScene (如果存在)
|
||
// 2. 深拷贝 m_editingScene -> m_runtimeScene
|
||
// - Play -> Stop:
|
||
// 1. 销毁 m_runtimeScene
|
||
// 2. 如果用户选择了 "Apply Changes",将 runtime 改动的 GameObject 同步回 editing
|
||
// 3. 恢复编辑模式
|
||
class EditorSceneManager {
|
||
public:
|
||
static EditorSceneManager& Get();
|
||
|
||
// 编辑场景 (编辑模式下使用)
|
||
Scene* GetEditingScene() { return m_editingScene.get(); }
|
||
|
||
// 运行时场景 (Play 模式下使用)
|
||
// 注意:运行时场景是编辑场景的副本,不是同一个对象
|
||
Scene* GetRuntimeScene() { return m_runtimeScene.get(); }
|
||
|
||
// Play/Stop 控制
|
||
enum class Mode {
|
||
Stopped, // 编辑模式
|
||
Playing, // 播放模式
|
||
Paused // 暂停模式
|
||
};
|
||
|
||
void Play(); // 开始播放:从 editing 拷贝到 runtime
|
||
void Pause(); // 暂停
|
||
void Unpause(); // 继续
|
||
void Stop(); // 停止播放:销毁 runtime,可选 Apply Changes
|
||
void Step(); // 单步执行一帧
|
||
|
||
Mode GetMode() const { return m_mode; }
|
||
|
||
// Apply Changes (Play -> Stop 时可选)
|
||
// 将 runtime 场景中的运行时数据同步回 editing 场景
|
||
enum class ApplyChangesMode {
|
||
None, // 不应用任何更改
|
||
All, // 应用所有更改
|
||
Selected // 只应用选中的GameObject
|
||
};
|
||
void SetApplyChangesMode(ApplyChangesMode mode);
|
||
void ApplyRuntimeChanges();
|
||
|
||
// 场景操作
|
||
void CreateNewScene();
|
||
void OpenScene(const String& path);
|
||
void SaveScene(const String& path);
|
||
|
||
// 撤销/重做
|
||
void Undo();
|
||
void Redo();
|
||
bool CanUndo() const;
|
||
bool CanRedo() const;
|
||
|
||
// GameObject操作
|
||
void DuplicateGameObject(GameObject* gameObject);
|
||
void DeleteGameObject(GameObject* gameObject);
|
||
void PasteGameObject();
|
||
void CopyGameObject(GameObject* gameObject);
|
||
|
||
// 预制件
|
||
void CreatePrefab(GameObject* gameObject, const String& path);
|
||
GameObject* InstantiatePrefab(const String& path);
|
||
void UnpackPrefab(GameObject* gameObject);
|
||
|
||
private:
|
||
void CopySceneToRuntime(); // 深拷贝编辑场景到运行时场景
|
||
void SyncRuntimeToEditing(); // 同步运行时更改回编辑场景
|
||
|
||
std::unique_ptr<Scene> m_editingScene;
|
||
std::unique_ptr<Scene> m_runtimeScene;
|
||
|
||
Mode m_mode = Mode::Stopped;
|
||
ApplyChangesMode m_applyChangesMode = ApplyChangesMode::None;
|
||
|
||
std::deque<UndoRedoAction> m_undoStack;
|
||
std::deque<UndoRedoAction> m_redoStack;
|
||
};
|
||
|
||
// 撤销/重做
|
||
class UndoRedoSystem {
|
||
public:
|
||
void PushAction(std::unique_ptr<IUndoRedoAction> action);
|
||
void Undo();
|
||
void Redo();
|
||
|
||
bool CanUndo() const { return !m_undoStack.empty(); }
|
||
bool CanRedo() const { return !m_redoStack.empty(); }
|
||
|
||
void Clear();
|
||
|
||
private:
|
||
std::deque<std::unique_ptr<IUndoRedoAction>> m_undoStack;
|
||
std::deque<std::unique_ptr<IUndoRedoAction>> m_redoStack;
|
||
size_t m_maxStackSize = 100;
|
||
};
|
||
|
||
// 编辑器工具
|
||
namespace Tools {
|
||
|
||
class EditorTool {
|
||
public:
|
||
virtual ~EditorTool() = default;
|
||
virtual void OnActivate() {}
|
||
virtual void OnDeactivate() {}
|
||
virtual void Update(float deltaTime) {}
|
||
virtual void OnSceneGUI() {}
|
||
virtual void OnObjectGUI(GameObject* gameObject) {}
|
||
|
||
virtual const char* GetName() const = 0;
|
||
virtual const char* GetIcon() const = 0;
|
||
|
||
protected:
|
||
bool m_active = false;
|
||
};
|
||
|
||
class SelectionTool : public EditorTool {
|
||
public:
|
||
const char* GetName() const override { return "Select"; }
|
||
void Update(float deltaTime) override;
|
||
void OnSceneGUI() override;
|
||
};
|
||
|
||
class MoveTool : public EditorTool {
|
||
public:
|
||
const char* GetName() const override { return "Move"; }
|
||
void Update(float deltaTime) override;
|
||
void OnSceneGUI() override;
|
||
};
|
||
|
||
class RotateTool : public EditorTool {
|
||
public:
|
||
const char* GetName() const override { return "Rotate"; }
|
||
void Update(float deltaTime) override;
|
||
void OnSceneGUI() override;
|
||
};
|
||
|
||
class ScaleTool : public EditorTool {
|
||
public:
|
||
const char* GetName() const override { return "Scale"; }
|
||
void Update(float deltaTime) override;
|
||
void OnSceneGUI() override;
|
||
};
|
||
|
||
class Gizmo {
|
||
public:
|
||
enum class Mode {
|
||
Translate,
|
||
Rotate,
|
||
Scale,
|
||
Rect,
|
||
Transform
|
||
};
|
||
|
||
enum class Space {
|
||
World,
|
||
Local
|
||
};
|
||
|
||
enum class PivotMode {
|
||
Center,
|
||
Pivot
|
||
};
|
||
|
||
void SetMode(Mode mode);
|
||
void SetSpace(Space space);
|
||
void SetPivot(PivotMode pivot);
|
||
|
||
void BeginManipulation(GameObject* gameObject);
|
||
void Draw(GameObject* gameObject);
|
||
void EndManipulation();
|
||
|
||
bool IsManipulating() const { return m_manipulating; }
|
||
Matrix4x4 GetManipulationDelta() const;
|
||
|
||
private:
|
||
Mode m_mode = Mode::Translate;
|
||
Space m_space = Space::World;
|
||
PivotMode m_pivot = PivotMode::Center;
|
||
bool m_manipulating = false;
|
||
GameObject* m_selectedGameObject = nullptr;
|
||
Matrix4x4 m_startMatrix;
|
||
};
|
||
|
||
// 编辑器相机
|
||
class EditorCamera {
|
||
public:
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void Update(float deltaTime);
|
||
|
||
void SetProjection(float fov, float aspect, float near, float far);
|
||
void SetOrthographic(float size, float near, float far);
|
||
|
||
Matrix4x4 GetViewMatrix() const;
|
||
Matrix4x4 GetProjectionMatrix() const;
|
||
|
||
// 控制
|
||
void Orbit(const Vector2& delta);
|
||
void Pan(const Vector2& delta);
|
||
void Zoom(float delta);
|
||
|
||
void FocusOn(GameObject* gameObject);
|
||
void FocusOn(const BoundingBox& bounds);
|
||
|
||
// 状态
|
||
float GetDistance() const { return m_distance; }
|
||
void SetDistance(float distance);
|
||
|
||
Vector3 GetPosition() const;
|
||
Vector3 GetForward() const;
|
||
Vector3 GetTarget() const { return m_target; }
|
||
|
||
private:
|
||
Vector3 m_target = Vector3::Zero();
|
||
float m_distance = 10.0f;
|
||
float m_pitch = 0.0f;
|
||
float m_yaw = 0.0f;
|
||
|
||
float m_fov = 60.0f;
|
||
float m_near = 0.1f;
|
||
float m_far = 1000.0f;
|
||
bool m_orthographic = false;
|
||
|
||
// 交互
|
||
bool m_isOrbiting = false;
|
||
bool m_isPanning = false;
|
||
};
|
||
|
||
} // namespace Tools
|
||
|
||
// 编辑器面板
|
||
namespace Panels {
|
||
|
||
class HierarchyPanel {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void SetSearchFilter(const String& filter);
|
||
void DrawGameObjectTree(GameObject* parent, int& idCounter);
|
||
|
||
private:
|
||
String m_searchFilter;
|
||
GameObject* m_contextMenuGameObject = nullptr;
|
||
};
|
||
|
||
class InspectorPanel {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void DrawGameObject(GameObject* gameObject);
|
||
void DrawComponent(uint32_t componentTypeId, void* component);
|
||
void DrawAddComponentMenu();
|
||
|
||
private:
|
||
GameObject* m_selectedGameObject = nullptr;
|
||
};
|
||
|
||
class SceneViewPanel {
|
||
public:
|
||
void OnGUI();
|
||
void Render();
|
||
|
||
Tools::EditorCamera& GetCamera() { return m_camera; }
|
||
|
||
private:
|
||
Tools::EditorCamera m_camera;
|
||
bool m_gridVisible = true;
|
||
bool m_gizmosVisible = true;
|
||
};
|
||
|
||
class GameViewPanel {
|
||
public:
|
||
void OnGUI();
|
||
void Render();
|
||
|
||
void SetResolution(int width, int height);
|
||
void SetFullscreen(bool fullscreen);
|
||
|
||
private:
|
||
int m_width = 1280;
|
||
int m_height = 720;
|
||
bool m_fullscreen = false;
|
||
bool m_vsync = true;
|
||
};
|
||
|
||
class ProjectPanel {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void DrawAssetBrowser();
|
||
void DrawFolderTree();
|
||
|
||
void OnAssetSelected(ResourceGUID guid);
|
||
|
||
private:
|
||
String m_currentPath;
|
||
std::vector<ResourceGUID> m_selectedAssets;
|
||
ViewMode m_viewMode = ViewMode::Grid;
|
||
};
|
||
|
||
class ConsolePanel {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void Log(const String& message, LogLevel level);
|
||
void Clear();
|
||
void Filter(LogLevel minLevel);
|
||
|
||
private:
|
||
struct LogEntry {
|
||
String message;
|
||
LogLevel level;
|
||
String source;
|
||
int64_t timestamp;
|
||
};
|
||
|
||
std::vector<LogEntry> m_logs;
|
||
LogLevel m_filterLevel = LogLevel::Info;
|
||
};
|
||
|
||
// 动画曲线编辑器
|
||
class AnimationCurveEditor {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void SetCurve(AnimationCurve* curve);
|
||
void AddKey(float time, float value);
|
||
void RemoveKey(int index);
|
||
|
||
private:
|
||
AnimationCurve* m_curve = nullptr;
|
||
int m_selectedKey = -1;
|
||
};
|
||
|
||
// 着色器编辑器
|
||
class ShaderEditor {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void OpenShader(const String& path);
|
||
void SaveShader();
|
||
void CompileShader();
|
||
|
||
void SetPreviewMesh(Mesh* mesh);
|
||
void SetPreviewRotation(const Vector3& rotation);
|
||
|
||
private:
|
||
String m_shaderPath;
|
||
bool m_compileErrors = false;
|
||
String m_errorMessage;
|
||
};
|
||
|
||
// 材质编辑器
|
||
class MaterialEditor {
|
||
public:
|
||
void OnGUI();
|
||
|
||
void OpenMaterial(Material* material);
|
||
void SaveMaterial();
|
||
|
||
void DrawProperty(MaterialProperty* property);
|
||
|
||
private:
|
||
Material* m_material = nullptr;
|
||
};
|
||
|
||
// 偏好设置
|
||
class PreferencesWindow : public EditorWindow {
|
||
public:
|
||
void OnGUI() override;
|
||
|
||
private:
|
||
void DrawGeneralSettings();
|
||
void DrawThemeSettings();
|
||
void DrawInputSettings();
|
||
void DrawShortcutSettings();
|
||
};
|
||
|
||
} // namespace Panels
|
||
|
||
// 编辑器渲染
|
||
class EditorRenderView {
|
||
public:
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void RenderSceneView(Panels::SceneViewPanel* panel);
|
||
void RenderGameView(Panels::GameViewPanel* panel);
|
||
|
||
void SetRenderTarget(RenderTexture* target);
|
||
|
||
private:
|
||
void SetupCamera(EditorCamera& camera);
|
||
void RenderGizmos();
|
||
|
||
RenderTexture* m_renderTarget = nullptr;
|
||
};
|
||
|
||
} // namespace Editor
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十五章 工具链 (Toolchain)
|
||
|
||
### 15.1 资源处理管道
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Tools {
|
||
|
||
// 资源处理器
|
||
class AssetProcessor {
|
||
public:
|
||
static AssetProcessor& Get();
|
||
|
||
void Initialize(const String& projectPath);
|
||
void Shutdown();
|
||
|
||
// 导入
|
||
void ImportAsset(const String& sourcePath);
|
||
void ImportAllAssets();
|
||
|
||
// 烘焙
|
||
void CookScene(Scene* scene, const String& outputPath);
|
||
void CookMaterial(Material* material, const String& outputPath);
|
||
void CookTexture(Texture* texture, const String& outputPath);
|
||
|
||
// 构建
|
||
void BuildProject(const BuildSettings& settings);
|
||
|
||
private:
|
||
void ProcessImportQueue();
|
||
void WriteCookedData(const String& path, const void* data, size_t size);
|
||
|
||
std::queue<String> m_importQueue;
|
||
};
|
||
|
||
// 着色器编译器
|
||
class ShaderCompiler {
|
||
public:
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
// 编译
|
||
CompiledShader Compile(const ShaderSource& source, const ShaderCompileOptions& options);
|
||
bool CompileFile(const String& inputPath, const String& outputPath,
|
||
const ShaderCompileOptions& options);
|
||
|
||
// 工具
|
||
void GenerateShaderIncludes();
|
||
void StripDebugInfo(CompiledShader& shader);
|
||
|
||
// 工具链
|
||
enum class ShaderProfile {
|
||
DXIL, // DirectX 12
|
||
SPIRV, // Vulkan
|
||
MSL, // Metal
|
||
GLSL, // OpenGL
|
||
WGSL // WebGPU
|
||
};
|
||
|
||
void SetProfile(ShaderProfile profile);
|
||
void AddPreprocessorDefine(const String& define);
|
||
|
||
private:
|
||
struct CompilerConfig {
|
||
ShaderProfile profile;
|
||
std::vector<String> defines;
|
||
bool generateDebugInfo = false;
|
||
bool optimize = true;
|
||
int optimizationLevel = 3;
|
||
};
|
||
|
||
CompilerConfig m_config;
|
||
};
|
||
|
||
// 场景烘焙器
|
||
class SceneCooker {
|
||
public:
|
||
void Cook(Scene* scene, const CookSettings& settings);
|
||
|
||
// 灯光烘焙
|
||
void BakeLightmaps(Scene* scene);
|
||
void BakeReflectionProbes(Scene* scene);
|
||
void BakeAmbientOcclusion(Scene* scene);
|
||
|
||
// 导航烘焙
|
||
void BakeNavigationMesh(Scene* scene);
|
||
|
||
// 遮挡剔除
|
||
void BakeOcclusionCulling(Scene* scene);
|
||
|
||
// 静态批处理
|
||
void BakeStaticBatches(Scene* scene);
|
||
|
||
private:
|
||
void CookGameObject(GameObject* gameObject);
|
||
void WriteCookedScene(const String& path, const CookedScene& data);
|
||
};
|
||
|
||
// 构建工具
|
||
class BuildTool {
|
||
public:
|
||
struct BuildSettings {
|
||
String outputPath;
|
||
String projectName;
|
||
|
||
// 平台
|
||
BuildPlatform platform;
|
||
BuildConfiguration config = BuildConfiguration::Release;
|
||
|
||
// 脚本
|
||
bool compileScripts = true;
|
||
bool generateDebugSymbols = false;
|
||
|
||
// 资源
|
||
bool compressAssets = true;
|
||
bool stripUnusedResources = true;
|
||
|
||
// 目标
|
||
bool buildExe = true;
|
||
bool buildDLC = false;
|
||
bool bundleResources = true;
|
||
};
|
||
|
||
void Build(const BuildSettings& settings);
|
||
void BuildPlayer(const BuildSettings& settings);
|
||
void BuildAssetBundle(const BuildSettings& settings);
|
||
|
||
private:
|
||
void PrepareBuildDirectory(const BuildSettings& settings);
|
||
void CompileScripts(const BuildSettings& settings);
|
||
void CookResources(const BuildSettings& settings);
|
||
void CopyEngineFiles(const BuildSettings& settings);
|
||
void LinkExecutable(const BuildSettings& settings);
|
||
};
|
||
|
||
// 性能分析器工具
|
||
class ProfilerCapture {
|
||
public:
|
||
void StartCapture();
|
||
void StopCapture();
|
||
|
||
void SaveCapture(const String& path);
|
||
void LoadCapture(const String& path);
|
||
|
||
// 分析
|
||
void GenerateReport();
|
||
float GetTotalFrameTime() const;
|
||
float GetCPUFrameTime() const;
|
||
float GetGPUFrameTime() const;
|
||
|
||
private:
|
||
struct FrameData {
|
||
uint64_t timestamp;
|
||
std::vector<ProfilerEvent> events;
|
||
};
|
||
|
||
std::vector<FrameData> m_frames;
|
||
bool m_capturing = false;
|
||
};
|
||
|
||
} // namespace Tools
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十六章 平台层 (Platform)
|
||
|
||
### 16.1 跨平台抽象
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Platform {
|
||
|
||
// 平台类型
|
||
enum class PlatformType {
|
||
Windows,
|
||
Linux,
|
||
macOS,
|
||
Android,
|
||
iOS,
|
||
Web,
|
||
PlayStation,
|
||
Xbox,
|
||
Nintendo
|
||
};
|
||
|
||
// 键码
|
||
enum class KeyCode {
|
||
None = 0,
|
||
A = 4, B = 5, C = 6, D = 7, E = 8, F = 9, G = 10,
|
||
H = 11, I = 12, J = 13, K = 14, L = 15, M = 16, N = 17,
|
||
O = 18, P = 19, Q = 20, R = 21, S = 22, T = 23, U = 24,
|
||
V = 25, W = 26, X = 27, Y = 28, Z = 29,
|
||
F1 = 122, F2 = 120, F3 = 99, F4 = 118, F5 = 96, F6 = 97,
|
||
F7 = 98, F8 = 100, F9 = 101, F10 = 109, F11 = 103, F12 = 111,
|
||
Space = 49, Tab = 48, Enter = 36, Escape = 53,
|
||
LeftShift = 56, RightShift = 60, LeftCtrl = 59, RightCtrl = 62,
|
||
LeftAlt = 58, RightAlt = 61,
|
||
Up = 126, Down = 125, Left = 123, Right = 124,
|
||
Home = 115, End = 119, PageUp = 116, PageDown = 121,
|
||
Delete = 51, Backspace = 51
|
||
};
|
||
|
||
// 鼠标按钮
|
||
enum class MouseButton {
|
||
Left = 0,
|
||
Right = 1,
|
||
Middle = 2,
|
||
Button4 = 3,
|
||
Button5 = 4
|
||
};
|
||
|
||
// 触摸状态
|
||
struct TouchState {
|
||
int touchId;
|
||
Vector2 position;
|
||
Vector2 deltaPosition;
|
||
float deltaTime;
|
||
int tapCount;
|
||
enum Phase { Began, Moved, Stationary, Ended, Canceled } phase;
|
||
};
|
||
|
||
// 指针事件
|
||
struct PointerEvent {
|
||
int pointerId;
|
||
Vector2 position;
|
||
Vector2 deltaPosition;
|
||
float pressure;
|
||
MouseButton button;
|
||
enum Type { Pressed, Released, Moved, Wheel, Hover } type;
|
||
};
|
||
|
||
// 按键事件
|
||
struct KeyEvent {
|
||
KeyCode keyCode;
|
||
bool alt;
|
||
bool ctrl;
|
||
bool shift;
|
||
bool meta;
|
||
enum Type { Down, Up, Repeat } type;
|
||
};
|
||
|
||
// 文本输入事件
|
||
struct TextInputEvent {
|
||
char character;
|
||
String text;
|
||
};
|
||
|
||
// 拖放事件
|
||
struct DragEvent {
|
||
Vector2 position;
|
||
Vector2 delta;
|
||
int pointerId;
|
||
};
|
||
|
||
// 文件变化事件
|
||
struct FileChangeEvent {
|
||
String path;
|
||
enum Type { Created, Modified, Deleted, Renamed } type;
|
||
};
|
||
|
||
// 手势事件
|
||
struct GestureEvent {
|
||
Vector2 position;
|
||
float deltaScale;
|
||
float deltaRotation;
|
||
int tapCount;
|
||
enum Type { None, Tap, DoubleTap, Pinch, Rotate, Pan } type;
|
||
};
|
||
|
||
// 窗口
|
||
class Window {
|
||
public:
|
||
virtual ~Window() = default;
|
||
|
||
virtual void Create(const WindowDesc& desc) = 0;
|
||
virtual void Destroy() = 0;
|
||
|
||
virtual void Show() = 0;
|
||
virtual void Hide() = 0;
|
||
virtual void Minimize() = 0;
|
||
virtual void Maximize() = 0;
|
||
virtual void Restore() = 0;
|
||
virtual void SetFullscreen(bool fullscreen) = 0;
|
||
|
||
virtual void SetTitle(const String& title) = 0;
|
||
virtual void SetSize(int width, int height) = 0;
|
||
virtual void SetPosition(int x, int y) = 0;
|
||
|
||
virtual bool IsClosed() const = 0;
|
||
virtual bool IsFocused() const = 0;
|
||
virtual bool IsMinimized() const = 0;
|
||
virtual bool IsMaximized() const = 0;
|
||
virtual bool IsFullscreen() const = 0;
|
||
|
||
virtual void* GetNativeHandle() const = 0;
|
||
|
||
// 事件
|
||
Event<int, int> OnResize;
|
||
Event<int, int> OnMove;
|
||
Event<> OnClose;
|
||
Event<> OnFocus;
|
||
Event<> OnBlur;
|
||
Event<> OnMinimize;
|
||
Event<> OnMaximize;
|
||
Event<> OnRestore;
|
||
};
|
||
|
||
// 输入
|
||
class InputSystem {
|
||
public:
|
||
// 键盘
|
||
bool IsKeyDown(KeyCode key) const;
|
||
bool IsKeyUp(KeyCode key) const;
|
||
bool IsKeyPressed(KeyCode key) const;
|
||
|
||
// 鼠标
|
||
Vector2 GetMousePosition() const;
|
||
Vector2 GetMouseDelta() const;
|
||
float GetMouseScrollDelta() const;
|
||
bool IsMouseButtonDown(MouseButton button) const;
|
||
bool IsMouseButtonUp(MouseButton button) const;
|
||
bool IsMouseButtonClicked(MouseButton button) const;
|
||
|
||
// 手柄
|
||
int GetJoystickCount() const;
|
||
bool IsJoystickConnected(int joystick) const;
|
||
Vector2 GetJoystickAxis(int joystick, int axis) const;
|
||
bool IsJoystickButtonDown(int joystick, int button) const;
|
||
|
||
// 触摸
|
||
int GetTouchCount() const;
|
||
TouchState GetTouch(int index) const;
|
||
|
||
// 手势
|
||
Event<GestureEvent&> OnGesture;
|
||
};
|
||
|
||
// 注意:FileSystem 定义在 Platform 命名空间中
|
||
// Core::IO 只保留流抽象 (IStream, FileReader, FileWriter)
|
||
}
|
||
|
||
namespace XCEngine {
|
||
namespace Platform {
|
||
|
||
// 文件系统 - 统一的跨平台文件系统抽象
|
||
class FileSystem {
|
||
public:
|
||
static FileSystem& Get();
|
||
|
||
// 路径操作
|
||
String GetWorkingDirectory();
|
||
String GetExecutablePath();
|
||
String GetUserDirectory();
|
||
String GetAppDataDirectory();
|
||
String GetTempDirectory();
|
||
|
||
// 文件操作
|
||
bool FileExists(const String& path);
|
||
bool DirectoryExists(const String& path);
|
||
bool CreateDirectory(const String& path);
|
||
bool DeleteFile(const String& path);
|
||
bool DeleteDirectory(const String& path);
|
||
|
||
// 读写
|
||
std::unique_ptr<IStream> OpenRead(const String& path);
|
||
std::unique_ptr<IStream> OpenWrite(const String& path);
|
||
std::unique_ptr<IStream> OpenAppend(const String& path);
|
||
|
||
// 遍历
|
||
void EnumerateFiles(const String& directory, const String& pattern,
|
||
std::vector<String>& results);
|
||
void EnumerateDirectories(const String& directory,
|
||
std::vector<String>& results);
|
||
|
||
// 观察
|
||
void WatchDirectory(const String& directory,
|
||
std::function<void(const FileChangeEvent&)> callback);
|
||
};
|
||
|
||
// 时间
|
||
|
||
// 时间
|
||
class Time {
|
||
public:
|
||
static float GetTime();
|
||
static float GetUnscaledTime();
|
||
static float GetDeltaTime();
|
||
static float GetUnscaledDeltaTime();
|
||
|
||
static void SetTimeScale(float scale);
|
||
static float GetTimeScale() { return m_timeScale; }
|
||
|
||
static uint64_t GetFrameCount() { return m_frameCount; }
|
||
static int GetFrameRate() { return m_frameRate; }
|
||
|
||
static void SetTargetFrameRate(int rate);
|
||
static void BeginFrame();
|
||
static void EndFrame();
|
||
|
||
private:
|
||
static float m_timeScale;
|
||
static uint64_t m_frameCount;
|
||
static int m_frameRate;
|
||
};
|
||
|
||
// 内存映射文件
|
||
class MemoryMappedFile {
|
||
public:
|
||
bool Open(const String& path);
|
||
void Close();
|
||
|
||
void* GetData() const { return m_data; }
|
||
size_t GetSize() const { return m_size; }
|
||
|
||
private:
|
||
void* m_handle = nullptr;
|
||
void* m_data = nullptr;
|
||
size_t m_size = 0;
|
||
};
|
||
|
||
// 进程
|
||
class Process {
|
||
public:
|
||
bool Launch(const String& command, const std::vector<String>& args);
|
||
void Terminate();
|
||
bool IsRunning() const;
|
||
|
||
int GetExitCode() const;
|
||
int WaitForExit();
|
||
|
||
void Write(const void* data, size_t size);
|
||
String ReadOutput();
|
||
String ReadError();
|
||
|
||
private:
|
||
void* m_handle = nullptr;
|
||
};
|
||
|
||
// 动态库
|
||
class DynamicLibrary {
|
||
public:
|
||
bool Load(const String& path);
|
||
void Unload();
|
||
|
||
void* GetFunction(const String& name);
|
||
bool IsLoaded() const;
|
||
|
||
private:
|
||
void* m_handle = nullptr;
|
||
};
|
||
|
||
// 系统信息
|
||
class SystemInfo {
|
||
public:
|
||
static String GetOSName();
|
||
static String GetOSVersion();
|
||
static String GetMachineName();
|
||
static String GetUserName();
|
||
|
||
static int GetProcessorCount();
|
||
static int GetProcessorCoreCount();
|
||
static int GetThreadCount();
|
||
|
||
static uint64_t GetTotalMemory();
|
||
static uint64_t GetAvailableMemory();
|
||
|
||
static String GetGPUName();
|
||
static uint64_t GetGPUMemory();
|
||
static int GetGPUMonitorCount();
|
||
|
||
static bool HasNvidiaGPU();
|
||
static bool HasAmdGPU();
|
||
static bool HasIntelGPU();
|
||
};
|
||
|
||
} // namespace Platform
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第十七章 构建与部署
|
||
|
||
### 17.1 CMake 项目结构
|
||
|
||
```
|
||
XCVolumeRenderer/
|
||
├── CMakeLists.txt # 根 CMake 配置
|
||
├── cmake/
|
||
│ ├── FindXXX.cmake # 第三方库查找
|
||
│ ├── XCEngineDefaults.cmake # 默认设置
|
||
│ └── Utils.cmake # 工具宏
|
||
│
|
||
├── engine/ # 引擎核心
|
||
│ ├── CMakeLists.txt
|
||
│ ├── include/
|
||
│ └── src/
|
||
│
|
||
├── editor/ # 编辑器
|
||
│ ├── CMakeLists.txt
|
||
│ └── src/
|
||
│
|
||
├── runtime/ # 运行时
|
||
│ ├── CMakeLists.txt
|
||
│ └── src/
|
||
│
|
||
├── tools/ # 工具链
|
||
│ ├── AssetProcessor/
|
||
│ ├── ShaderCompiler/
|
||
│ └── SceneCooker/
|
||
│
|
||
└── third_party/ # 第三方库
|
||
├── CMakeLists.txt
|
||
├── imgui/
|
||
├── stb/
|
||
└── ...
|
||
```
|
||
|
||
### 17.2 CMake 配置示例
|
||
|
||
```cmake
|
||
# 根 CMakeLists.txt
|
||
cmake_minimum_required(VERSION 3.20)
|
||
project(XCGameEngine VERSION 1.0.0)
|
||
|
||
# 选项
|
||
option(BUILD_EDITOR "Build editor" ON)
|
||
option(BUILD_RUNTIME "Build runtime" ON)
|
||
option(BUILD_TOOLS "Build tools" ON)
|
||
option(BUILD_SHADERS "Build shaders" ON)
|
||
|
||
# 加载工具
|
||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||
include(XCEngineDefaults)
|
||
|
||
# 依赖
|
||
find_package(Threads REQUIRED)
|
||
find_package(D3D12 REQUIRED)
|
||
find_package(Vulkan REQUIRED)
|
||
|
||
# 子目录
|
||
add_subdirectory(third_party)
|
||
add_subdirectory(engine)
|
||
|
||
if(BUILD_EDITOR)
|
||
add_subdirectory(editor)
|
||
endif()
|
||
|
||
if(BUILD_RUNTIME)
|
||
add_subdirectory(runtime)
|
||
endif()
|
||
|
||
if(BUILD_TOOLS)
|
||
add_subdirectory(tools)
|
||
endif()
|
||
```
|
||
|
||
### 17.3 构建流程
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ Build Pipeline │
|
||
├─────────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Source Code ──► Compile ──► Link ──► Engine Library │
|
||
│ │ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ Assets ──► Import ──► Cook ──► Pack ──► Resource Bundle │
|
||
│ │
|
||
│ │ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ Shaders ──► Compile ──► Pack ──► Shader Cache │
|
||
│ │
|
||
│ │ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ Final Output │ │
|
||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │
|
||
│ │ │ Executable │ │ Resources │ │ Engine Libraries │ │ │
|
||
│ │ │ (EXE/DLL) │ │ (.pak) │ │ (.lib/.dll) │ │ │
|
||
│ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ │
|
||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 第十八章 总结与实现建议
|
||
|
||
### 18.1 架构核心要点
|
||
|
||
1. **分层设计**: Platform → Core → Engine → Editor/Runtime
|
||
2. **组件系统**: 类Unity的GameObject+Component模式
|
||
3. **渲染抽象**: 跨 API 的渲染接口,便于扩展
|
||
4. **资源管理**: 完整的导入→处理→缓存→加载管道
|
||
5. **工具链**: 从源代码到最终产品的完整构建系统
|
||
|
||
### 18.2 实现优先级建议
|
||
|
||
#### 第一阶段 (基础框架)
|
||
- [ ] 数学库 (Vector, Matrix, Quaternion, Transform)
|
||
- [ ] 基础容器 (Array, String, HashMap)
|
||
- [ ] 内存管理 (Allocator, Pool)
|
||
- [ ] 线程系统 (Thread, Mutex, TaskSystem)
|
||
- [ ] 日志系统
|
||
- [ ] 文件系统抽象
|
||
|
||
#### 第二阶段 (组件系统 + 渲染)
|
||
- [ ] 组件系统核心 (GameObject, Component)
|
||
- [ ] 基础组件 (Transform, RenderMesh)
|
||
- [ ] 渲染抽象层 (Device, CommandList)
|
||
- [ ] D3D12/Vulkan 后端
|
||
- [ ] 基础渲染管线 (GBuffer, Lighting)
|
||
|
||
#### 第三阶段 (功能系统)
|
||
- [ ] 资源系统 (ResourceManager, AssetDatabase)
|
||
- [ ] 场景系统 (Scene, SceneManager)
|
||
- [ ] 物理系统 (基础碰撞检测)
|
||
- [ ] 输入系统
|
||
- [ ] UI 框架
|
||
|
||
#### 第四阶段 (编辑器)
|
||
- [ ] 编辑器 UI (ImGui)
|
||
- [ ] 场景视图/游戏视图
|
||
- [ ] 层级面板/检视面板
|
||
- [ ] 资源浏览器
|
||
- [ ] 工具 (Gizmo, 编辑器相机)
|
||
|
||
#### 第五阶段 (高级功能)
|
||
- [ ] 动画系统
|
||
- [ ] 粒子系统
|
||
- [ ] 音频系统
|
||
- [ ] 网络系统
|
||
- [ ] 脚本系统
|
||
|
||
### 18.3 代码组织建议
|
||
|
||
```
|
||
engine/src/
|
||
├── Core/ # 1-2周
|
||
│ ├── Math/
|
||
│ ├── Containers/
|
||
│ ├── Memory/
|
||
│ ├── Threading/
|
||
│ └── Debug/
|
||
├── Components/ # 2-3周
|
||
│ ├── GameObject.cpp
|
||
│ ├── Component.cpp
|
||
│ └── System.cpp
|
||
├── Renderer/ # 3-4周
|
||
│ ├── Device.cpp
|
||
│ ├── CommandList.cpp
|
||
│ ├── Pipeline.cpp
|
||
│ └── Passes/
|
||
├── Resources/ # 2周
|
||
│ ├── ResourceManager.cpp
|
||
│ ├── AssetDatabase.cpp
|
||
│ └── Loaders/
|
||
├── Scene/ # 1周
|
||
├── Physics/ # 2-3周
|
||
├── Scripting/ # 3-4周 (可选)
|
||
└── Platform/ # 1周
|
||
├── Windows.cpp
|
||
└── ...
|
||
|
||
editor/src/
|
||
├── Application.cpp # 1周
|
||
├── Panels/ # 2周
|
||
├── Tools/ # 2周
|
||
├── Windows/ # 2周
|
||
└── ImGui/ # 1周
|
||
```
|
||
|
||
### 18.4 技术选型建议
|
||
|
||
| 子系统 | 推荐方案 | 备选 |
|
||
|--------|----------|------|
|
||
| 图形 API | D3D12 + Vulkan | Metal, OpenGL |
|
||
| 物理 | PhysX | Bullet, Box2D |
|
||
| 脚本 | C# (Mono/.NET) | Lua, AngelScript |
|
||
| UI (编辑器) | ImGui | Qt, Custom |
|
||
| UI (运行时) | 自研 Canvas | DearImgui, RmlUI |
|
||
| 资源格式 | 自研 Binary + JSON | glTF, USD |
|
||
| 压缩 | LZ4 + ZSTD | LZMA, LZHAM |
|
||
| 网络 | 自研 / ENet | LiteNetLib |
|
||
|
||
### 18.5 性能目标
|
||
|
||
- 60 FPS 稳定运行 (1080p, 中等画质)
|
||
- 10000+ 实体同屏
|
||
- 加载时间 < 3秒 (典型场景)
|
||
- 编辑器响应 < 16ms
|
||
|
||
---
|
||
|
||
*文档版本: 1.15*
|
||
*最后更新: 2026-03-13*
|