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*
|