ShitEngine 1.4.2
基于 C++20 与 SDL3 的轻量级 2D 游戏引擎
载入中...
搜索中...
未找到
Scene.h
浏览该文件的文档.
1#pragma once
2#include <cstdint>
3#include <typeindex>
4#include <vector>
5#include <memory>
6#include <unordered_map>
7#include <string>
8
9#include "../Core/Core.h"
10#include "ShitEngine/Core/Log.h"
12
13namespace Shit {
14 class System;
15 // 前向声明
16 class Component;
17 class CameraComponent;
18 class SceneManager;
19 class GameObject;
20 class Prefab;
21 class Behavior;
23
36 class SHIT_API Scene final {
37 friend class GameObject;
38 public:
39 explicit Scene(const std::string& name);
41
42 // 禁止拷贝和移动构造
43 Scene(const Scene&) = delete;
44 Scene& operator=(const Scene&) = delete;
45 Scene(Scene&&) = delete;
46 Scene& operator=(Scene&&) = delete;
47
48 void init();
49 void update();
50
51 // --- 固定步长驱动 ---
52 static constexpr float FIXED_TIME_STEP = 1.0f / 60.0f;
53 static constexpr int MAX_FIXED_STEPS_PER_FRAME = 3;
54 void destroy();
55
57 bool hasSystems() const { return !m_systems.empty(); }
58
63
66 GameObject* findGameObjectByName(const std::string& name);
67
68 void addGameObject(std::unique_ptr<GameObject>&& gameObject);
69 GameObject* createGameObject(const std::string& name);
70 GameObject* instantiate(const Prefab& prefab, const std::string& name = "");
71 void removeGameObject(GameObject* gameObject);
72 void removeGameObjectByName(const std::string& name);
73
75 bool registerComponent(Component* component);
78
79 template <typename T>
81 static_assert(std::is_base_of_v<System, T>, "必须继承自 System 基类");
82
83 auto type_index = std::type_index(typeid(T));
84
85 if (hasSystem<T>()) {
86 return getSystem<T>();
87 }
88
89 auto new_system = std::make_unique<T>();
90 T* new_system_ptr = new_system.get(); // 返回的指针
91
92 new_system_ptr->setScene(this);
93
94 // 先入表再 init():System::init() 会补扫场景中未注册的组件并广播 registerComponent。
95 // 若尚未加入 m_systems,新系统将收不到已存在组件的 onComponentAttached,
96 // "组件先加、驱动系统后注册"的补挂机制会失效。
97 m_systemsMap[type_index] = std::unique_ptr<System>(new_system.release());
98 m_systems.push_back(new_system_ptr);
99 m_isSystemsNeedSort = true;
100
101 new_system_ptr->init();
102
103 ST_CORE_TRACE("Scene : {} 已添加系统 {}", m_name, typeid(T).name());
104
105 return new_system_ptr;
106 }
107
108 template <typename T>
110 static_assert(std::is_base_of_v<System, T>, "必须继承自 System 基类");
111
112 m_pendingRemoveSystems.push_back(std::type_index(typeid(T))); // 延迟移除
113 }
114
115 template <typename T>
117 static_assert(std::is_base_of_v<System, T>, "必须继承自 System 基类");
118 auto type_index = std::type_index(typeid(T));
119
120 if (auto it = m_systemsMap.find(type_index); it != m_systemsMap.end()) {
121 return static_cast<T*>(it->second.get());
122 }
123 return nullptr;
124 }
125
126template <typename T>
127 bool hasSystem() {
128 static_assert(std::is_base_of_v<System, T>, "必须继承自 System 基类");
129
130 return m_systemsMap.contains(std::type_index(typeid(T)));
131 }
132
133 // ── 按字符串名称的系统管理(供编辑器运行时使用) ──
134
137 System* registerSystem(const std::string& typeName);
138
140 System* getSystem(const std::string& typeName) const;
141
143 bool hasSystem(const std::string& typeName) const;
144
146 void unregisterSystem(const std::string& typeName);
147
149 std::vector<std::string> getRegisteredSystemTypeNames() const;
150
152 void setSystemPriority(const std::string& typeName, int priority);
153
155 void unregisterSystemsBySource(const std::string& source);
156
159
160 // --- getter & setter ---
161 const std::string& getName() const { return m_name; }
162 std::vector<std::unique_ptr<GameObject>>& getGameObjects() { return m_gameObjects; }
163
164 void setName(const std::string& name) { m_name = name; }
165
169 uint64_t getGeneration() const { return m_generation; }
170
172 bool containsGameObject(const GameObject* gameObject) const;
173
176 Component* componentByUuid(uint64_t uuid) const { return m_uuidMap.count(uuid) ? m_uuidMap.at(uuid) : nullptr; }
177
178 private:
179 void processPendingAdditions(); // 处理延迟添加
180 void processPendingRemoveSystems();
181 void bumpGeneration() { ++m_generation; }
182
185 void indexComponentUuid(Component* component);
187 void unindexComponentUuid(Component* component);
188
189 std::string m_name; // 场景名称
190 std::vector<std::unique_ptr<GameObject>> m_gameObjects; // 游戏物体
191 std::vector<std::unique_ptr<GameObject>> m_pendingAdditions; // 延迟添加
192 uint64_t m_generation = 0;
193 std::unordered_map<uint64_t, Component*> m_uuidMap;
194
195 std::unordered_map<std::type_index, std::unique_ptr<System>> m_systemsMap; // 注册的系统
196 std::vector<System*> m_systems; // 缓存的系统
197 std::vector<std::type_index> m_pendingRemoveSystems;
198 bool m_isSystemsNeedSort = false;
199 bool m_isInited = false;
200 float m_fixedAccumulator = 0.0f;
201 };
202}
#define SHIT_API
定义 Core.h:14
#define ST_CORE_TRACE(...)
定义 Log.h:67
行为基类 —— 用于编写自定义游戏逻辑
定义 Behavior.h:22
相机组件,定义"从哪个角度观察世界"
定义 CameraComponent.h:16
组件基类
定义 Component.h:25
游戏物体类
定义 GameObject.h:23
预制体,可重复生成相同配置的 GameObject
定义 Prefab.h:23
渲染组件基类
定义 RendererComponent.h:18
friend class GameObject
GameObject 结构变更(组件增删/改名/改父)时通知 bumpGeneration
定义 Scene.h:37
void addGameObject(std::unique_ptr< GameObject > &&gameObject)
延迟添加 GameObject(帧末生效)
Scene & operator=(const Scene &)=delete
void init()
注册默认系统(BehaviorSystem + RenderSystem + UIRenderSystem),幂等
uint64_t getGeneration() const
场景结构代数:任何对象增删/组件增删/改名/改父都会递增。 编辑器据此判断"场景内容是否变化",及时重建场景树、校验选中态, 避免播放中对象被游戏逻辑销毁后仍持有悬垂指针。
定义 Scene.h:169
static constexpr float FIXED_TIME_STEP
固定步长(秒):onFixedUpdate 与物理模拟的共同节拍
定义 Scene.h:52
void unregisterSystemsBySource(const std::string &source)
卸载指定来源注册的所有系统(插件卸载前调用,防止卸载 DLL 后 vtable 悬垂)
Component * componentByUuid(uint64_t uuid) const
按持久 UUID 查找组件(ComponentRef<T> 懒解析 / 编辑器拖拽引用共用) 组件已移除或对象已销毁后返回 nullptr(UUID 索引随组件生命周期维护)。
定义 Scene.h:176
void destroy()
销毁所有对象与系统
void removeGameObjectByName(const std::string &name)
按名称标记销毁
const std::string & getName() const
定义 Scene.h:161
void removeGameObject(GameObject *gameObject)
按指针标记销毁
System * registerSystem(const std::string &typeName)
按类型名注册系统(通过反射 Factory 创建实例)。幂等(已有则返回现有)。 失败(类型未注册/无工厂/非 System 派生)返回 nullptr 并 WARN。
bool containsGameObject(const GameObject *gameObject) const
对象是否仍在当前场景容器中(地址比较,供编辑器校验旧选中指针)
void unregisterComponent(Component *component)
组件卸下广播(组件 onDetach 调用)。
bool hasSystems() const
是否已注册任何 System(SceneManager 用于自动初始化,防止漏调 init() 导致空场景)
定义 Scene.h:57
System * getSystem(const std::string &typeName) const
按类型名查询系统(返回 nullptr 表示未注册)
std::vector< std::string > getRegisteredSystemTypeNames() const
返回当前已注册系统的类型名列表(按优先级排序)
void flushPendingSystemRemovals()
立即处理待移除系统队列(热重载卸载 DLL 前调用,确保 vtable 悬垂前销毁系统)
bool hasEnabledCamera()
场景中是否存在已启用的相机(含延迟添加的 pending 对象)。 运行态加载场景时对象先进 m_pendingAdditions、m_gameObjects 为空, 只扫正式容器会误判"没有相机"而重...
Scene(Scene &&)=delete
void setName(const std::string &name)
定义 Scene.h:164
GameObject * createGameObject(const std::string &name)
创建并添加 GameObject
void setSystemPriority(const std::string &typeName, int priority)
调整系统优先级(即时生效,下一帧 update 前重排序)
Scene(const Scene &)=delete
GameObject * instantiate(const Prefab &prefab, const std::string &name="")
从预制体实例化
T * getSystem()
定义 Scene.h:116
void unregisterSystem()
定义 Scene.h:109
void update()
更新所有 System(固定步循环 + 变步长遍历)+ 处理延迟操作
T * registerSystem()
定义 Scene.h:80
void unregisterSystem(const std::string &typeName)
按类型名延迟移除系统
bool hasSystem(const std::string &typeName) const
按类型名判断系统是否已注册
static constexpr int MAX_FIXED_STEPS_PER_FRAME
单渲染帧最大固定步数(超出丢弃,防死亡螺旋)
定义 Scene.h:53
GameObject * findGameObjectByName(const std::string &name)
遍历全部对象(正式 + pending),返回第一个名为 name 的对象。 与 hasEnabledCamera 同理,覆盖 pending 防止运行态漏判。
std::vector< std::unique_ptr< GameObject > > & getGameObjects()
定义 Scene.h:162
bool hasSystem()
定义 Scene.h:127
Scene(const std::string &name)
Scene & operator=(Scene &&)=delete
bool registerComponent(Component *component)
组件挂载广播(组件 onAttach 调用)。分发给可处理的系统,返回是否有系统认领。
场景管理器(单例)
定义 SceneManager.h:19
System 基类
定义 System.h:19
定义 AnimationClip.h:12
@ T
定义 KeyCode.h:37