服务器端游戏场景优化

对于mmo类游戏,场景往往是游戏的性能瓶颈,优化场景逻辑是游戏开发工作中必不可少的工作。最好是前期开发阶段,就能解决掉场景性能热点,否则后期很难改动。

游戏场景主要优化场景内消息的分发处理。尤其是场景内玩家的移动。如果100人在场景内同时移动,就要相互转发100,就要产生100*100个移动包。很多视野外的人其实是不需要知道你的位置,或者你不要看到视野外的人位置,所以首先去掉大量无效的包发送是关键。

游戏中对场景移动处理往往分两种,1、按照地图网格移动,一般只需要发送几个拐点就可以(可以利用recast navigation开源库实现)。2、将地图按照像素网格,一般客户端会将地图处理成一个个菱形网格,这个时候发送的就是格子坐标。地图移动方式多是采用A* 算法。

地图移动优化思路解析:

1、服务器首先将地图模拟划分成一个一个zone的九宫格,参考(https://blog.csdn.net/chinabhlt/article/details/102564984),

利用这种方式首先就减少大量无效的移动转发消息。按照zone进行zone内玩家移动位置消息发送。

2、减少发包量,由tcp发包原理可以知道,如果一个一个进行发包,显然是产生更多的流量,最好是服务器攒够一定的包数,统一发送最好。进行延迟发包。

3、利用多线程处理。利用多线程发送移动包,避免发包造成其他逻辑处理的延迟卡顿。

4、利用双缓存模式,由于多线程使用必然会加锁,加锁容易造成性能消耗严重,甚至造成性能不如单线程。双缓存可以使读写缓存分离,减少锁的占用。

伪代码:

scene.cpp

player->move():

move(pos)
{
    move_info->set_pos(pos);
    new_zone_id = m_zone_mgr.GetZoneId(pos);
    // 判断是否切zone
    if (old_zone_id == new_zone_id)
	{
		m_zone_mgr.AddMoveInfo(old_zone_id, move_info);  // --》 向zone内添加移动消息
	}
	else
	{
		m_zone_mgr.ChangeZone(user, old_zone_id, new_zone_id);
		m_zone_mgr.AddMoveInfo(user, old_zone_id, new_zone_id, move_info);
		user->SetZoneId(new_zone_id);
	}

}

// 延迟发包处理
new thread({
    sleep(30ms);
    zone_mgr.send_move();        // 每个zone 开发发送已有移动包
})


zonemgr.cpp  ....

zone.cpp

write_move_infos
read_move_infos

send_move_info()
{
    read_move_infos* pRead_move_info = nullptr;
    {
        lock()
        pRead_move_info = pwrite_move_infos;
        pwrite_move_infos = malloc(write_move_infos);
    }
    send_read_move_info(pRead_move_info);
    free(pRead_move_info);
}

// malloc, free 调用自己的内存池,并非真的malloc free

write_move_info(move_info)
{
    lock()
    pwrite_move_infos->add(move_info);
}

最后优化就是提高机器性能了。

你可能感兴趣的:(游戏开发)