写在前面的一段话:
之前准备用LuaServer写一个简单moba手游,后来觉得,LuaServer毕竟是前公司内部的产品,不是绝对开源的,也因着别的一些原因,决定放弃更新LuaServer相关的。
但个人学习不能停是不是,哈哈哈…今儿起,准备捣鼓捣鼓KBEngine。KBEngine之前也没有接触过,Unity也好久没碰过了,于是乎,就准备把这两者结合下,实现从入门到“放弃”的一个小目标吧。
这系列文章,会伴随自己业余时间,便实现代码便总结记录,当做一份学习笔记。
这里准备利用KBEngine作为服务端引擎,将Unity官网的坦克大战demo进行改造,目标是实现一个联机版坦克大战,同步方式采用状态同步来完成。
从上层功能开发入手,然后深入到源码层,以此完成一次自我学习的过程~同时,代码会在github上同步更新。
阶段目标
- 环境搭建
- 客户端能和KBEngine完成通信
- Server端完成基本的从匹配到进入战场的功能,客户端做出响应
环境搭建
KBEngine官网:KBEngine官方网站
KBEngine源码:github源码
Unity版本:Unity 2019.1.0f2 (64-bit)
坦克大战demo:在Unity的Asset Store里面搜索关键字"Tanks"免费获取
服务端基础配置:WampServer
KBEngine默认是需要mysql数据库支持的,为了便于开发,减少前期投入的时间,利用WampServer傻瓜式一键式搭建一个简易的mysql运行环境。
关于KBEngine环境的具体搭建,参考官网,官网的环境搭建文档还是很详细的,文档传送门在此:点我!传送门
流程设计
简单了解了下,KBEngine的cell部分主要承担的是space内相关的数据操作,比如移动、战斗等等,base上承担的则是一些基础性的东西。(这是刚接触时,给我的感觉,可能说的不准备,等待后续深入学习再具体看)。基于这个认识,我们从登陆、匹配到进入战场的第一阶段目标,基本上和cell是无关的,全部在base上实现得了。
先奉上一份上述操作的设计流程时序图:
相关说明
- Account是kbe引擎层在客户端登录时默认创建的第一个entity实体,配置第一个实体的文件在assets\res\server\kbengine.xml里面的accountEntityScriptType字段
- Account的任务就是验证登录相关性,所以在验证完成后,我会创建出一个PlayerAvatar的对象,并把Account的proxy转移给PlayerAvatar,此后与客户端交互的对象就从Account转移到PlayerAvatar身上了。同时,真正进入相应space空间的是PlayerAvatar这个entity而非Account,Account在此时是可以考虑destroy了的。(对于proxy的解释,放在后续文章里,这里简单理解为通过他就可以和客户端通信就好~)。
- SpaceMgr是一个全局的Space管理器,所有的Space(大厅、战场等)全部由这个管理器来维护管理,SpaceMgr本身也是一个Entity。
相关代码
Account.py
def becomePlayerAvatar(self):
"""
从Account成为Avatar
:return:
"""
avatar = KBEngine.createEntityLocally('PlayerAvatar', {})
if avatar:
DEBUG_MSG("Account[%i].becomePlayerAvatar\n" % self.id)
self.activeAvatar = avatar
self.giveClientTo(self.activeAvatar)
PlayerAvatar.py
def onClientEnabled(self):
INFO_MSG("PlayerAvatar::onClientEnabled, ready to enter space")
spaceMgr = KBEngine.globalData['SpaceMgr']
spaceMgr and spaceMgr.enterSpace(self, SpaceType.SPACE_TYPE_HALL)
SpaceRoom.py
def avatarReqMatch(self, avatarID):
INFO_MSG("[SpaceRoom], %i, %i, avatar:%s reqMatch." % (self.id, self.uType, avatarID))
self._wait_to_match_avatar_set.add(avatarID)
matchNum = len(self._wait_to_match_avatar_set)
if matchNum >= MatchArgs.BATTLE_ROOM_MATCH_PLAYER_NUM:
INFO_MSG("[SpaceRoom], %i, %i, ready to enter battle room" % (self.id, self.uType))
for _ava_id in self._wait_to_match_avatar_set:
_avatar = self._avatar_dict.get(_ava_id, None)
_avatar and _avatar.client.onEnterBattleRoom()
self._wait_to_match_avatar_set = set()
return
for ava_id in self._wait_to_match_avatar_set:
_avatar = self._avatar_dict.get(ava_id, None)
if not _avatar:
continue
_avatar.client.onMatch(matchNum)
上述源码地址
至此,一个特别特别版的初步目标达成了,可以从客户端发起登录、匹配、完成匹配的流程。这个版本里面,硬编码写死了2人匹配,匹配完成后直接跳到熟悉的坦克大战场景。。
画面很突兀,也没润色,有画面感的版本会在第二篇文章里面给出,这篇文章的个人小目标就是实现一次基本的通信流程。
guthub源码地址: 联机版坦克大战github地址