状态同步模式下的游戏掉线重连
2017-08-06 23:32
381 查看
状态同步模型下,所有的游戏逻辑、数据都会保存在服务端。对于开房间式的游戏(比如5V5这类),玩家的状态都可以在每一个房间room内维护着。
当检测到有玩家触发掉线事件时,首先根据玩家客户端连接的tcp连接号(client_id)去索引到所在的房间,然后从房间内维护的所有玩家的信息列表(players)中找到该玩家,这时候不要将改玩家对象从players中移除,而是采取标记的方式,不如修改player对象的一个状态值为下线状态。这样子设计的好处在于,如果玩家重新连接,可以快速找到掉线前所在的房间,而且不需要再new一个player对象加入到players中去,只需要修改下players中对应的player的在线状态即可。在该player掉线的过程中,room内所有的player一样在进行正常的逻辑运算,如果这时候掉线的player被打死(状态信息发送了变化),等玩家重新连接后边会直接看到被改变后的状态。
但是,这样子会存在一个问题,就是每次断开连接再次连接后,服务端收到的同一个玩家的tcp连接好是发生了变化的。所以,对于player类的设计需要特别注意,我们需要给player设计一个上下线都不变的fixed_client_id,这个值只在第一次刚开房间的时候赋值,之后都不会被改变。之所以需要维护这么一个固定的id号,是因为这类游戏,在客户端也往往会维持这么一份所有玩家的信息表,一般都可以采用不同玩家不同的client_id来索引到客户端中每个敌方单位。但是每次玩家掉线重连后由于更新了client_id,服务端会按照最新的client_id将rpc消息转发给对应的客户端,但是客户端方面存储敌方单位的client_id并没有被更新,这样子往往就无法把敌方单位的操作表现出来。这时候fixed_client_id的作用就体现出来了。在服务器做状态运算时,在修改敌方单位状态的时候,需要把敌方单位的fixed_client_id传给客户端,但是在转发rpc消息时要采用最新的client_id。如此便解决了掉线重连的问题。
local room = { room_id = -1, --房间id offline_player_num = 0, --房间内的掉线人数 frame_id = 0, --帧序号 players = players, --玩家列表(这是存储玩家类的表) frame_msg_list = {}, --帧数据列表(一局游戏的所有帧数据) tmp_frame_msg_list = {}, --临时的帧数据列表 atk_list = {}, --维护战斗道具的列表(如飞行中的子弹 frame_time_id = -1, --帧消息定时器id colider_time_id = -1, --碰撞计算定时器id }
当检测到有玩家触发掉线事件时,首先根据玩家客户端连接的tcp连接号(client_id)去索引到所在的房间,然后从房间内维护的所有玩家的信息列表(players)中找到该玩家,这时候不要将改玩家对象从players中移除,而是采取标记的方式,不如修改player对象的一个状态值为下线状态。这样子设计的好处在于,如果玩家重新连接,可以快速找到掉线前所在的房间,而且不需要再new一个player对象加入到players中去,只需要修改下players中对应的player的在线状态即可。在该player掉线的过程中,room内所有的player一样在进行正常的逻辑运算,如果这时候掉线的player被打死(状态信息发送了变化),等玩家重新连接后边会直接看到被改变后的状态。
但是,这样子会存在一个问题,就是每次断开连接再次连接后,服务端收到的同一个玩家的tcp连接好是发生了变化的。所以,对于player类的设计需要特别注意,我们需要给player设计一个上下线都不变的fixed_client_id,这个值只在第一次刚开房间的时候赋值,之后都不会被改变。之所以需要维护这么一个固定的id号,是因为这类游戏,在客户端也往往会维持这么一份所有玩家的信息表,一般都可以采用不同玩家不同的client_id来索引到客户端中每个敌方单位。但是每次玩家掉线重连后由于更新了client_id,服务端会按照最新的client_id将rpc消息转发给对应的客户端,但是客户端方面存储敌方单位的client_id并没有被更新,这样子往往就无法把敌方单位的操作表现出来。这时候fixed_client_id的作用就体现出来了。在服务器做状态运算时,在修改敌方单位状态的时候,需要把敌方单位的fixed_client_id传给客户端,但是在转发rpc消息时要采用最新的client_id。如此便解决了掉线重连的问题。
local player = { client_id = client_id, --唯一id(掉线重连后会更新) fixed_client_id = client_id, --固定的id(只在第一次开房间时和client_id同时赋值,在掉线重连后也不更新) account = account, --用户名 log = Log:new("boe.player_" .. account), status = 1, --玩家状态 1:在线 -1:离线 0:掉线 hp = INIT_HP, --血量 }
--玩家重新上线处理器 function M.on_reconnection(client_id,room) M[client_id] = room end -- 玩家下线事件处理器 function M.on_disconnected(client_id) local room = M.get(client_id) if room then room:on_offline(client_id) --通知该房间内client_id的玩家掉线了 M[client_id] = nil --移除掉线玩家client_id所索引的房间(因为重连后的clien_id是变了的) log:info("room.offline_players's num = " .. room.offline_player_num) if room.offline_player_num < 2 then return end --没有全部掉线则不销毁房间 timer_queue:erase(room.frame_time_id) --清空房间定时器 timer_queue:erase(room.colider_time_id) M.erase(room) room:on_disconnected() --房间内存清理 if room ~= nil then room = nil --内存清理 end log:info("room_mgr:on_disconnected") end -- if room end -- on_disconnected()
相关文章推荐
- 状态同步模式下的游戏掉线重连
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
- 状态模式与有限状态机 &行为树(游戏开发)
- Unity游戏设计模式之状态模式实现
- [★] .NET 偶尔连接的设计策略 -联机状态- 脱机模式- 数据同步
- ESFramework 开发手册(08) -- 重登陆模式与掉线重连
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
- 【游戏设计模式】之三 状态模式、有限状态机 & Unity版本实现
- 游戏 场景同步 实现(状态同步)
- 游戏后台状态同步与帧同步
- [心跳] 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连
- 游戏编程模式 - 状态模式
- 游戏中的设计模式一(单例模式与状态模式)
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
- Java设计模式之从[游戏中的兵种状态转换]分析状态(State)模式
- 【unity】RPG游戏鼠标指针管理系统【单利模式】(游戏中,不同状态对于不同指针)
- Unity客户端框架笔记(状态模式和策略模式在游戏中的应用)
- DB2 HADR的4种同步模式、5种备机状态、3个超时参数
- 移动游戏 状态同步 帧同步
- 游戏开发中的设计模式——1.状态模式