首先放个房间示例的资源路径https://github.com/u3dkbe/kbengine_unity3d_balls

这个例子很简单,客户端点击登录按钮后即进入场景,同时生成大量NPC。鼠标点击可移动吃分。不过这里只关心脚本涉及初始化这块。kbengine的服务器用python写脚本,各种系统回调以及自己写的回调夹杂在一起,不熟悉会相当很晕。。所以写这个也权当笔记。。。

首先客户端向服务端发送登录消息后,服务端自动检测默认设置为帐号属性的类(这个DEMO里面是Avatar)。然后自动调用Avatar BASE部分的初始化代码。初始化完成后,会调用一个回调函数:onEnitiesEnabled。这个回调是引擎接口,只需要往里面添加自己的代码就好。demo在这个回调里面,利用全局参数获得大厅HALL的指针,调用了enterRoom函数。

def onEntitiesEnabled(self):"""KBEngine method.该entity被正式激活为可使用, 此时entity已经建立了client对应实体, 可以在此创建它的cell部分。"""INFO_MSG("Avatar[%i] entities enable. mailbox:%s" % (self.id, self.client))# 如果销毁玩家计时器已经开启了,此处玩家又上线了那么应该取消计时器if self._destroyTimer > 0:self.delTimer(self._destroyTimer)self._destroyTimer = 0# 如果玩家存在cell, 说明已经在地图中了, 因此不需要再次进入地图if self.cell is None:# 玩家上线了或者重登陆了, 此处告诉大厅,玩家请求登陆到游戏地图中KBEngine.globalData["Halls"].enterRoom(self, self.cellData["position"], self.cellData["direction"], self.roomKey)

那这个HALL类是哪里来的呢?其实是在引擎初始化脚本里面。当启动服务器时,调用了KBEngine的base部分的引擎接口onBaseAppReady。在这个回调里面通过KBEngine.createBaseLocally函数创建了HALL类。

def onBaseAppReady(isBootstrap):"""KBEngine method.baseapp已经准备好了@param isBootstrap: 是否为第一个启动的baseapp@type isBootstrap: BOOL"""INFO_MSG('onBaseAppReady: isBootstrap=%s, appID=%s, bootstrapGroupIndex=%s, bootstrapGlobalIndex=%s' % \(isBootstrap, os.getenv("KBE_COMPONENTID"), os.getenv("KBE_BOOTIDX_GROUP"), os.getenv("KBE_BOOTIDX_GLOBAL")))# 安装监视器Watcher.setup()if isBootstrap:# 创建大厅KBEngine.createBaseLocally( "Halls", {} )

回到HALL.enterRoom这个函数来,通过调用findRoom来寻找房间,这个函数查找是否存在已有的房间,若不存在的话则通过KBEngine.createBaseAnywhere异步创建Room类。随后判断,如果房间异步创建还未成功,则先把要加入房间的avatar信息保存下来。

def enterRoom(self, entityMailbox, position, direction, roomKey):"""defined method.请求进入某个Room中"""roomDatas = self.findRoom(roomKey, True)roomDatas["PlayerCount"] += 1roomMailbox = roomDatas["roomMailbox"]if roomMailbox is not None:roomMailbox.enterRoom(entityMailbox, position, direction)else:DEBUG_MSG("Halls::enterRoom: space %i creating..., enter entityID=%i" % (roomDatas["roomKey"], entityMailbox.id))roomDatas["enterRoomReqs"].append((entityMailbox, position, direction))
def findRoom(self, roomKey, notFoundCreate = False):"""查找一个指定房间,如果找不到允许创建一个新的"""roomDatas = self.rooms.get(roomKey)# 如果房间没有创建,则将其创建if not roomDatas:if not notFoundCreate:return FIND_ROOM_NOT_FOUND# 如果最后创建的房间没有满员,则使用最后创建的房间key,否则产生一个新的房间唯一KeyroomDatas = self.rooms.get(self.lastNewRoomKey)if roomDatas is not None and roomDatas["PlayerCount"] < GameConfigs.ROOM_MAX_PLAYER:return roomDatasself.lastNewRoomKey = KBEngine.genUUID64()# 将房间base实体创建在任意baseapp上# 此处的字典参数中可以对实体进行提前def属性赋值KBEngine.createBaseAnywhere("Room", \{"roomKey" : self.lastNewRoomKey,    \}, \Functor.Functor(self.onRoomCreatedCB, self.lastNewRoomKey))roomDatas = {"roomMailbox" : None, "PlayerCount": 0, "enterRoomReqs" : [], "roomKey" : self.lastNewRoomKey}self.rooms[self.lastNewRoomKey] = roomDatasreturn roomDatasreturn roomDatas

Room被异步调用创建后,首先是base部分的初始化。demo在这个初始化代码里面调用了createInNewSpace函数,异步创建Room的cell部分。Room cell部分的创建成功后,会调用Base部分的回调函数onGetCell。demo在这个回调函数里面,调用了HALL.onRoomGetCell,而这个函数利用先前保存的avatar信息,调用avatar.creatCellEntity来创建avatar的cell部分。avatar cell创建成功后同样会调用BASE部分的onGetCell回调。至此,avatar正式加入场景。看到这里,有没有觉得一堆回调让人很晕。。。

def onGetCell(self):"""KBEngine method.entity的cell部分实体被创建成功"""DEBUG_MSG("Room::onGetCell: %i" % self.id)KBEngine.globalData["Halls"].onRoomGetCell(self, self.roomKey)
def onRoomGetCell(self, roomMailbox, roomKey):"""defined method.Room的cell创建好了"""self.rooms[roomKey]["roomMailbox"] = roomMailbox# space已经创建好了, 现在可以将之前请求进入的玩家全部丢到cell地图中for infos in self.rooms[roomKey]["enterRoomReqs"]:entityMailbox = infos[0]entityMailbox.createCell(roomMailbox.cell)self.rooms[roomKey]["enterRoomReqs"] = []
def createCell(self, space):"""defined method.创建cell实体"""self.createCellEntity(space)

avatar只是我们控制的角色,那那些NPC是怎么加入场景的呢?在ROOM的cell部分的初始化代码里,利用addTimer加入了一个定时器。这个定时器干嘛的呢?通过定期回调onTimer,调用了room cell部分的balanceMass函数,通过KBEngine.createEntity函数生成了大量的NPC。所以这里demo其实是演示了一个通过定时器,避免同时大量创建物体NPC的办法,减轻服务器压力。

def onTimer(self, id, userArg):"""KBEngine method.使用addTimer后, 当时间到达则该接口被调用@param id      : addTimer 的返回值ID@param userArg    : addTimer 最后一个参数所给入的数据"""if TIMER_TYPE_DESTROY == userArg:self.onDestroyTimer()elif TIMER_TYPE_BALANCE_MASS == userArg:self.balanceMass()

KBEngine 房间示例创建脚本调用解读相关推荐

  1. ironpython调用c dll_IronPython脚本调用C#dll示例

    上两篇IronPython脚本的文章介绍了与C#紧密结合的示例,这里还将提供一个与C#结合更紧密的示例,直接调用C#编写的DLL. 我们还是沿用了上篇文章的代码(其实这里可以直接使用IronPytho ...

  2. MySQL存储过程的创建及调用

    阅读目录:MySQL存储过程_创建-调用-参数 存储过程:SQL中的"脚本" 1.创建存储过程 2.调用存储过程 3.存储过程体 4.语句块标签 存储过程的参数 1.in:向过程里 ...

  3. 函数定义、函数参数、跨脚本调用函数

    2.6.函数使用 函数定义 示例(文件名称为func1.sh): #!/bin/bash ##定义函数 hello() { echo "Hello there today's date is ...

  4. 转 Oracle DBCA高级玩法:从模板选择、脚本调用到多租户

    但凡是学过Oracle的同学,对DBCA(Database Configuration Assistant, DBCA)都不会陌生,有了这个工具,使得创建数据库成为可能.而DBCA本身有图形和静默两种 ...

  5. (原创)使用TimeStamp控制并发问题[示例]-.cs脚本

    TimeStamp.aspx.cs代码(C#),已调试通过:   1using System;   2using System.Collections;   3using System.Compone ...

  6. 【Groovy】Groovy 脚本调用 ( Groovy 脚本中调用另外一个 Groovy 脚本 | 调用 evaluate 方法执行 Groovy 脚本 | 参数传递 )

    文章目录 一.Groovy 脚本中调用另外一个 Groovy 脚本 1.调用 evaluate 方法执行 Groovy 脚本 2.参数传递 二.完整代码示例 1.调用者 Groovy 脚本 2.被调用 ...

  7. 使用shell脚本调用mysql数据库存储过程,并设置定时任务

    本来是要mysql数据库中创建事件任务来,定时执行存储过程,做数据传输的...后来由于种种原因,就使用crontab来定时执行,调用存储过程. 实现这个数据传输分为两步: 第一步:编写shell脚本调 ...

  8. Unity(创建脚本)

    #一.描述 记录第一课时,脚本的创建与使用基本的API #二.学习记录 (一)创建一个Cube方块 (二)在cube组件上添加一个脚本,选中cube组件,在屏幕右侧有着cube的组件属性栏,点击Add ...

  9. maven jpa_使用Hibernate 4,JPA和Maven的架构创建脚本

    maven jpa 这种情况很简单–您想要在构建应用程序时生成数据库模式创建脚本(然后在目标数据库上执行脚本),这在Hibernate 3中相对容易,因为有 hibernate3-maven-plug ...

最新文章

  1. linux文件管理相关操作
  2. Spring Boot + Dataway :接口不用写,配配就出来?
  3. PAT甲级1137 Final Grading:[C++题解]结构体、排序、哈希表、结构体构造函数、结构体内写函数
  4. 88. Leetcode 剑指 Offer 14- I. 剪绳子 (动态规划-基础题)
  5. HDU2026 首字母变大写
  6. OpenGL绘制二个不同颜色的三角形的实例
  7. ML.NET机器学习、API容器化与Azure DevOps实践(四):持续集成与k8s持续部署
  8. 程序员在周末学习的8个实用技术
  9. Linux 中最常用 150 个命令汇总
  10. iphone 低版本渲染不出来内容的一种解决办法
  11. 你认识什么是前端吗?你是合格的前端吗?
  12. 局部光照与全局光照的区别
  13. 设计模式之六个创建型模式的相关知识,简单易懂。
  14. Maven_Maven简介
  15. 计算机专业试讲10分钟教案,10分钟试讲教案模板.doc
  16. 搭建个人内网穿透服务
  17. 联想Idealpad 710s - 13IKB 重装系统教程以及遇到的问题
  18. castle典范英语 storm_求典范英语theMasked Cleaning Ladies 第二篇save the day梗概和
  19. Compose 学习笔记(一)—— Compose 初探
  20. Android 音频录音与播放

热门文章

  1. WebStorm、Idea使用git账户密码重置
  2. python存储16bit和32bit图像
  3. ESP8266/ESP32/nodeMcu/wemos D1 MINI开发板用TFT_eSPI库驱动ST7789(240*240)TFT显示屏
  4. 《闻官军收河南河北》 杜甫
  5. tanlianjiyejiangemiao
  6. java粒子特效_程序员20分钟搞定粒子效果, 仅仅200行代码
  7. 城市内涝一维二维耦合技术及在城市排水防涝领域中的实践应用
  8. 云效平台性能测试功能:一个基于Jmeter的性能压测平台
  9. Java 操作 ElasticSearch
  10. pdf编辑软件哪个好?编辑pdf的软件分享一款,像word一样好用!