鉴于目前游戏引擎已经可以自由添加和移除Entity,并且可以向其中添加和移除Component,创建一个可以存储当前Scene信息的工具变得格外重要。
设计思路
由于游戏引擎中的Scene由Entity和它的Component组成,那么保存一个Scene就是保存这些信息。因此,我们可以使用序列化和反序列化工具,当需要保存时,将这些信息序列化为文本文件;当需要读取时,从文件路径中获取这个文本文件,然后执行反序列化。
YAML(Yet Another Markup Language)是一种人类可读的、层级结构清晰的序列化格式,广泛用于配置文件、资源描述、数据保存等场景。相比JSON,更简洁、支持注释和多种复杂结构。
代码实现
类SceneSerializer声明:当定义这个类的实例时,要在构造函数中要传入一个需要序列化的Scene实例,也就是告诉它需要序列化的目标。因此,在类Scene中,要定义一个友元类SceneSerializer,以便访问它的所有变量。
class SceneSerializer
{
public:
SceneSerializer(const Ref<Scene>& scene);
void Serialize(const std::string& filepath);
void SerializeRuntime(const std::string& filepath);
bool Deserialize(const std::string& filepath);
bool DeserializeRuntime(const std::string& filepath);
private:
Ref<Scene> m_Scene;
};
序列化函数Serializer():遍历当前Scene中的所有Entity,对其调用函数SerializeEntity(),记录所有Componnet的信息
void Serialize(const std::string& filepath)
{
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Scene" << YAML::Value << "Untitled";
out << YAML::Key << "Entities" << YAML::Value << YAML::BeginSeq;
m_Scene->m_Registry.each([&](auto entityID)
{
Entity entity = { entityID, m_Scene.get() };
if (!entity) return;
SerializeEntity(out, entity);
});
out << YAML::EndSeq;
out << YAML::EndMap;
std::ofstream fout(filepath);
fout << out.c_str();
}

Leave a comment