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);
			}
		}

至此  完成对象生成。对此配套的需要写一堆工具,来生成这些序列化文件 。

Scroll Up