StickEngine-架构4-反序列化-服务端篇
整体概述是 http://dreamyouxi.com:7129/blog/1203
由于服务器战斗和客户端采取类似的架构,都有类似的概念(GameObject,Prefab,GetComponent,BoxCollider等),在资源上就可以做的很容易了。
序列化分为两部分,第一步是从io文件反序列化为内存Prefab对象,第二步是从Prefab对象,生成各种class的数据。
第一步:
template<typename Class> inline void DeSerializeRigidbody(Prefabs * pre, Class& obj) { bool ok = false; do { PARSE_OBJECT_MEMBER(pre->hasRigidbody, "hasRigidbody"); PARSE_OBJECT_MEMBER(pre->rigidbody.useGravity, "useGravity"); PARSE_OBJECT_MEMBER(pre->rigidbody.isKinematic, "isKinematic"); PARSE_OBJECT_MEMBER(pre->rigidbody.mass, "mass"); PARSE_OBJECT_MEMBER(pre->rigidbody.drag, "drag"); PARSE_OBJECT_MEMBER(pre->rigidbody.angularDrag, "angularDrag"); } while (false); } template<typename Class> inline void DeSerializeCapsuleColliders(Prefabs * pre, Class& obj2) { for (auto it = obj2.begin(); it != obj2.end(); ++it) { auto &obj = it->GetJsonObject(); pre->capsuleColliders.emplace_back(CapsuleCollider::Serialize()); auto &col = pre->capsuleColliders[pre->capsuleColliders.size() - 1]; bool ok = false; PARSE_OBJECT_MEMBER(col.radius, "radius"); PARSE_OBJECT_MEMBER(col.height, "height"); PARSE_OBJECT_MEMBER(col.direction, "direction"); PARSE_OBJECT_MEMBER(col.isTrigger, "isTrigger"); } }
第二步:
Prefab生成GameObject或者 CppBehaviour
/* * Author: caoshanshan * Email: me@dreamyouxi.com */ #pragma once #include "battle/BaseAPI.h" #include "battle_app/BattleMisc.h" class BallisticSimulater :public CppBehaviour { DEFINE_SUB_CLASS(CLASS_ID_BallisticSimulater, BallisticSimulater, CppBehaviour); public: class Serialize : public Super::Serialize { public: float speed = 0.0f; float damage = 0; float lifetime = 6.0f; public: void DeSerialize(CppBehaviourSerializeData & data) { TryParseObjectMember(data, speed, "speed"); TryParseObjectMember(data, damage, "damage"); TryParseObjectMember(data, lifetime, "lifetime"); } }; Serialize serialize; void* GetSerializeField()override { return &serialize; } //----------------------------end of 协议部分 virtual int GetEventCallbackMask()override { return BehaviourEventCallbackMaskUpdate; } };
在这里有几个点相比Unity的实现,是有一些不同的:
1.服务器内存较大,允许通过内存换时间,因此目前启动时会把所有Prefab加载出来。
2.构造GameObject时,会直接进行memcpy,而非逐个反序列化,以达到最大速度,形如:
int size = this->cppscripts.size(); for (int i = 0; i < size; i++) { auto &buffer = cppscripts[i]; if (buffer.classid > 0 && buffer.data && buffer.size > 0) { CppBehaviour::Ptr cls = CreateInternalCppBehiviourClassObject(buffer.classid); if (cls) { //class which is build-in } else { if (Prefabs::CREATE_CPP_CLASS && Prefabs::SERIALIZE_CPPBEHAVIOUR) { //调用自定义初始化数据 cls = Prefabs::CREATE_CPP_CLASS(buffer.classid); assert(cls); if (!cls) { //未定义 的class 在序列文件中是不允许的 assert(false); continue; } } else { //invalid hook assert(false); continue; } } void *target = cls->GetSerializeField(); if (target) { ::memcpy(target, buffer.data, buffer.size); ret->AddComponentCppBehaviourInternal(cls); } else { //there has not any data will be serialized } } else { LOG_DEBUG("invalid cpp serialize data"); assert(false); } }
至此 完成对象生成。对此配套的需要写一堆工具,来生成这些序列化文件 。