游戏匹配和结算之防御式编程
在开发球球游戏的过程中,为了解决事先没有考虑到的问题,最终的实现和设计有所出入。其中有一部分是关于防御式编程的心得,我想单独拿出来说一下。
相关文章:游戏匹配和结算设计 , 游戏匹配和结算实现
游戏第一个版本出去,在外网我们遇到很多意想不到的问题。比如有些玩家打完一局比赛,会反复获得奖励,我们猜测是重复结算引起的。还有些玩家打完一局比赛,没有结算,导致业务服认为玩家没有完成比赛,要求玩家重连回原来的比赛,但是连到房间服会发现房间不存在,进入黑屏状态。为此我增加了很多防御式的代码。
-
最初的设计里并没有RemovePlayer消息,因为我认为RemovePlayer是由结算引起的,所以业务服收到房间结算消息(RoomResult)或者玩家结算消息(PlayerResult),就可以移除掉对应玩家。但实际上,结算业务偶尔会出现问题,RoomResult/PlayerResult消息不会发送,影响到RemovePlayer的处理。增加RemovePlayer消息后,不管结算业务是否异常,都会向业务服发送RemovePlayer消息。
-
当玩家请求进入房间服时,发现房间不存在,第一会通知玩家返回逻辑服,第二会通知逻辑服,移除该房间,防止玩家陷入“请求进入房间服-返回业务服”的循环。
-
当房间服增加玩家时,可能存在相同id的老的玩家,此时需要先移除老玩家。而移除老玩家是异步执行的,这就需要在场景中管理老玩家。理论上这种情况是不会出现的,玩家只有结束一局游戏,才能在逻辑服开始下一局游戏。但是并不排除逻辑服出现异常,误认为游戏已结束,提前开始下一局游戏的匹配。
-
房间一旦结算,设置gameOver flag,防止重复结算。
-
房间的定时器一旦停止,设置terminated flag,防止定时器重新启动。
-
当玩家结算后,从房间服移除玩家数据。当场景结算后,从房间服移除场景内所有玩家数据和场景数据。防止在结算后,调用玩家或场景相关操作。