一款已上市MMO手游地图同步方案总结

1. 客户端地图格子的相关知识

  在2.5D的MMO游戏里,角色是通过3D的方式渲染,2D的地图是通过2D的方式显示,所以在客户端一般会有三个坐标系:


a) 3D坐标系:所有需要3D渲染的角色和光效,都以3D坐标系中定位。

b) 2D坐标系:用来定位和绘制固定的2D地图元素,比如草皮、马路等。

c) 3D坐标里的格子坐标系:用来实现打掩码、自动寻路和进行一些坐标配置(比如NPC和怪物初始的位置)。使用格子坐标,一是为了方便打掩码和进行自动寻路的计算(经典的A*寻路),二是为了更方便查找坐标的具体位置。


  端游使用的格子大小一般为(64, 32),手游的精确度要求低一些,可以用(100, 50),即3D坐标系里长为100宽为50的矩形,即是格子坐标系里的一个坐标。示例图如下:


一款已上市MMO手游地图同步方案总结


2. 服务器同步大格子:9宫格

  MMO游戏里,玩家要能看到地图上所有角色的行为,这就需要将其它玩家的动作都通过网络数据同步过来。同步一般使用9宫格来确定,哪些玩家的数据要同步过来,然后自己的行为要同步给哪些玩家。


  服务器大格子的大小,以3*3的格子要总比客户端显示范围要大一点为原则。比客户端大一点,是为了预留资源加载的时间。


  如下图所示,绿色表示手机客户端的显示区域,当角色A在格子6中时,他可以看到1,2,3,5,6,7,9,10,11这9个格子里的内容,那么当他的状态发生变化时,就需要同步给在这9个格子里的所有玩家;同样,当这9个格子里的有玩家或者怪物的状态改变时,也需要都同步给角色A。


一款已上市MMO手游地图同步方案总结


  当角色A移动到角色B所在的格子(7),则他将不再看到1,5,9这三个格子里的内容(玩家和怪物),同时他将新看到4,8,12这三个格子里的地图内容。所以这个过程中,服务器要下发消息,删除角色A所在的客户端里的1,5,9这三个格子里的地图内容,同时下发消息新增4,8,12这三个格子里的地图内容(类型一)。


  推荐大格子具体的大小,按客户端iPhone4S的960*640分辨来制定,取屏幕长宽的1/2大一些,可以定为640*360。


3. 角色的移动同步

  地图上角色的同步可以分为位移的同步和行为(比如放技能)的同步。这里主要讨论位移的同步方式。


  位移同步的目的是为了将自己的位置变化发给服务器,然后由服务器通过9宫格的方式转发给周围的其他玩家。


  有的端游是以客户端格子的基本单位进行同步,当玩家从一个格子移动到了另一个格子时,就发消息通知给服务器。这种方式的缺点就是:


一、同步的延迟。玩家从一个格子开始移动,移动到另一个格子后,才发消息给服务器,服务器再转发给其它客户端,那其它客户端的玩家位置,总会有一点延后。

二、当网络不稳定的时候,很容易看到其它玩家不是均速的移动,比如玩家位置没动,然后一下子瞬移到了下一个格子。


  我们采用的方式,是同步状态的变化,然后由客户端来触发服务器对大格子跨越的判断:


d) 当玩家点击地图上某个地方,或者改变了摇杆方向,玩家的运行状态就变化了,即向某个坐标点移动。状态变化的时候,客户端就立即给服务器发消息,然后服务器进行转发。这样如果忽略了网络的延迟,那这个角色在所有客户端上,几乎是同时开始移动。


  如果移动过程中没有其它变化,则整个移动过程中只有一次消息同步。这里需要处理一个问题,就是服务器需要知道这个角色什么时候跨越了服务器的同步大格子,当角色跨越了同步大格子时,服务器就需要进行第二节里(类型一)的操作。


e) 如何判断角色的移动过程中跨越了同步大格子,有的游戏里采用服务器判断的方式,即根据角色的移动速度和方向,计算出跨越的时刻,然后使用一个Timer来触发。同时如果服务器要取这个角色的当前位置,则需要通过运动公式来进行计算。这个方案相对精确一些,但比较复杂,服务器也需要为每一个移动的角色设定一个Timer,对服务器的性能有所影响。


  我们采用的方式,是由客户端判断角色每移动一小段距离,然后发消息通知服务器,服务器不对这个消息进行转发,而只是判断是否跨越了大格子,同时记录下这个坐标,作为角色的当前位置。这一小段距离可以取100左右,值取得越大时,消息发送频率越小,但服务器的同步大格子跨越判断和角色当前位置就越不精确。


  因为是直接同步的运行状态,所以客户端发给服务器的坐标单位是3D坐标系里单位,而不是3D坐标系格子的坐标单位。这样就更加精确,一点点距离的移动,都能准确同步。


f) 同步运动状态的一个问题是,如果玩家操作很频繁,比如快死了逃跑时,疯狂地点地图,这时运动状态变化的非常快,如果每个状态的变化都同步给服务器,再加上广播,那消息量是很大的。


  所以需要设置一个状态同步的最短时间,当运动状态变化很快时,则将状态变化的消息缓存在客户端,同时加一个Timer跟踪。当马上有新的状态变化消息出来时,则进行替换,同时更新Timer。当没有状态变化的消息出来时,Timer到时间了就会触发,将缓存的状态变化的消息,发给服务器。


  这样通过消息缓存加上Timer的处理,既实现了运行状态同步的最短时间限制,也保证了最后有效的运行状态会稍晚一点点发送给服务器。


4. 怪物的同步

  怪物的同步在传统的端游里,是完全由服务器的怪物AI系统触发,客户端只是纯粹的接受服务器下发的怪物状态数据。对于手机游戏里,由于手机上很难出现像PC里那样的外挂,所以怪物的AI可以考虑放在客户端触发,同时减少怪物的状态同步。详细说明如下:


a) 怪物的随机移动不同步


  在地图上,怪物都会有一个固定的位置。怪物没有进入战斗状态时,就会在这个固定位置的周围走来走去,随机的移动。这个随机的移动由每个客户端自己控制,这样怪物的随机移动,就不用消息广播进行同步了。


  由于客户端自己控制怪物的随机走动,所以会出现不同客户端里,怪物位置不一样的问题。但由于怪物随机移动的范围较小,所以这个问题不是很明显,在手机上是可以接受的。角色打怪时,是扇形的伤害范围,所以即使怪物坐标在不同的客户端有点不一致,打怪的效果也是可以接受的。


b) 怪物的行为同步


  当有角色攻击被动怪物,或者进入主动怪物的视野范围内时,怪物的AI就被这个角色所在的客户端锁定了,同时怪物进入攻击状态。攻击的判断完全由锁定怪物AI的客户端进行处理,同时这个客户端会将这个怪物的行为上发到服务器,由服务器广播给周围的其他玩家。


  怪物的AI锁定,使用抢占式,即谁最先发消息给服务器申请怪物的AI锁定,谁就获得了怪物的控制权,直到怪物死亡或脱离战斗状态。


  怪物可以每进行一次攻击,客户端就发一个消息给服务器。这样做,消息还是有点多,特别是一群怪围着几个角色进行攻击时,消息广播还是有点多。所以可以将状态的概念向上扩大,只同步怪物在攻击哪个玩家,而不同步每一次的攻击,然后由每个客户端根据怪物固定的攻击速度各自去表现。这样一个怪去攻击一个玩家,就会只有一次消息广播了。


c) 精英怪和BOSS怪的AI


  精英怪和BOSS怪由于数量较少,而且比较重要,所以不能由客户端来申请AI控制权,而是服务器根据某种策略来控制。所使用的策略可以考虑角色的伤害值、防御值、角色与BOSS的距离远近等,根据这些因素,服务器计算出BOSS怪当前最适合攻击的对象(比如血量最少的玩家,最脆弱的法师等),然后将AI控制权发给那个客户端,由那个客户端控制攻击行为,同时通过消息让服务器同步给其他玩家。


  总结:怪物的同步方式的选择,就是要尽量减少消息的广播,同时让游戏效果在可接受的范围内。怪物AI的这个处理方式,实际上是同时省去了游戏服务器的怪物AI模块(端游一般是专门用的一个进程或者另外一台物理服务器来进行怪物AI的计算),从而简化了MMO游戏的开发难度,同时保证了较好的游戏体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

策略模式与简单工厂模式区别(转)

最近一直在抽时间研究设计模式,之前对设计模式也有一定的了解,但是都没有平心静气的去研究过,只是了解了一些皮毛,最近打算再深入研究一下,重新打开了设计模式的数据,对之前的疑问一个个的刨根问底&#xf…

c语言中枚举类型的长度,C中的枚举类型数据的大小是多少?

这是一个C面试测试问题不是家庭作业。#include using namespace std;enum months_t { january, february, march, april, may, june, july, august, september,october, november, december} y2k;int main (){cout << "sizeof months_t is " << sizeof(m…

求平方根sqrt()函数的底层算法效率问题

我们平时经常会有一些数据运算的操作&#xff0c;需要调用sqrt&#xff0c;exp&#xff0c;abs等函数&#xff0c;那么时候你有没有想过&#xff1a;这个些函数系统是如何实现的&#xff1f;就拿最常用的sqrt函数来说吧&#xff0c;系统怎么来实现这个经常调用的函数呢&#xf…

android espresso跨程序,Android Espresso:依次运行多个测试

我正在尝试使用Espresso forAndroid进行一系列测试.运行之间似乎没有关闭活动.一次测试后,无论应用程序状态如何,左侧为下一次测试.如何用Espresso来实现&#xff1f;错误报告中提供的修复程序的问题是,这将仅在整个套件的完成时执行.如果你想在每次测试后都有一个干净的活动堆…

C#中字符串的内存分配与驻留池

刚开始学习C#的时候&#xff0c;就听说CLR对于String类有一种特别的内存管理机制&#xff1a;有时候&#xff0c;明明声明了两个String类的对象&#xff0c;但是他们偏偏却指向同一个实例。如下&#xff1a; String s1 “Hello”; String s2 “Hello”; //s2和s1的实际值都…

signature=f2388c4f1bce538cc797410d9560f03b,KSHV strategies for host dsDNA sensing machinery

摘要&#xff1a;The innate immune system utilizes pattern recognition receptors cyclic GMP-AMP synthase(cGAS)to sense cytosolic double-stranded(ds) DNA and initiate type 1 interferon signaling and autophagy pathway, which collaborate to limit pathogen infe…

Unity 内存管理

一&#xff1a;资源类型 GameObject, Transform, Mesh, Texture, Material, Shader, noxss和各种其他Assets。 二&#xff1a;AssetBundle文件内存镜像 来自文件就用CreateFromFile(注意这种方法只能用于standalone程序&#xff09;这是最快的加载方法。也可以来自Memory,用…

1.逐帧动画shader

最近项目压力不大&#xff0c;抽时间看了些关于shader和游戏引擎的书籍&#xff0c;准备开始shader的学习。 在网上看到这位前辈&#xff08;http://blog.sina.com.cn/s/articlelist_2312702844_6_1.html&#xff09;写的博客&#xff0c;觉得很不错&#xff0c;学习曲线应该很…

panel中html怎么写,panel控件有什么用 请写出Panel控件的用途

当多个panel控件重叠时,把一个panel的visible/设置为true,其它的设置为f例如有3个panel&#xff0c;分别为panel1,panel2,panel3 如果重叠的话&#xff0c;把他们的大小设置为相同大小&#xff0c;直接通过上下层来控制即可&#xff0c;例如想要panel2显示出来&#xff0c;就用…

html页面如何实现搜索功能,使用jQuery怎么实现一个页面关键字搜索功能

使用jQuery怎么实现一个页面关键字搜索功能发布时间&#xff1a;2021-01-04 16:46:38来源&#xff1a;亿速云阅读&#xff1a;136作者&#xff1a;Leah这篇文章给大家介绍使用jQuery怎么实现一个页面关键字搜索功能&#xff0c;内容非常详细&#xff0c;感兴趣的小伙伴们可以参…

html相对定位向上偏移,使用CSS的相对定位和偏移量

这是利用CSS相对定位和偏移写成的表单输入框效果&#xff0c;不是以前用的表格那种&#xff0c;也没有用UL li&#xff0c;觉得借此示例可练习一下CSS,特别是CSS的定位和布局方面的知识&#xff0c;了解top,bottom,left,right这些偏移量属性的用法。CSS相对定位和偏移写成的表单…

2.转动的地球shader

原理很简单&#xff0c;根据时间对uv中的x轴进行位移&#xff0c;对于地面和云层&#xff0c;取不同的移动速度&#xff0c;分别计算对应的uv坐标&#xff0c;再根据uv坐标从地面和云层的纹理中分别取出对应的值&#xff0c;最后把两者用lerp函数进行混合作为最终结果。 下边的…

3.顶点外扩方法实现的描边shader

描边shader的实现有很多种&#xff0c;顶点外扩是其中之一。顶点外扩的原理是用2个Pass 渲染物体2次第一遍:描边&#xff0c;顶点沿法线方向外拓后用黑色渲染。外扩这一步的实现是在投影空间&#xff0c;也就是2D的&#xff0c;根绝法线的x和y值进行外扩&#xff0c;因为是沿着…

为此计算机所有用户安装加载项,安装Office 2013后,无法在计算机上安装Outlook加载项...

我使用Outlook Add in模板和VSTO在visual studio 2010中实现了Outlook添加&#xff0c;我使用MSI安装程序(在visual studio 2010中创建)为它创建了一个安装..我能够在所有机器上安装它(x86和x64) ) .最近我尝试在安装了Office 2013的计算机上安装相同的安装程序并收到以下错误&…

4.边缘光照的描边shader

【思路】&#xff1a;面向摄像机的物体&#xff0c;它的表面法线【normal】和视角向量【viewDir】的【夹角】越靠近边缘就越大。那么就可以根据这个夹角进行处理&#xff0c;夹角越大&#xff0c;那么发射光越强&#xff0c;就可以实现我们想要的效果。 Shader "Study/4_O…

html 怎么设置cooki,怎么设置浏览器接受cookie

怎么设置浏览器接受cookie把浏览器设置成接受cookie方法&#xff0c;以IE11为例&#xff1a; 1&#xff0c;打开IE浏览器&#xff0c;在菜单栏上点击“工具”&#xff0c;弹出下拉菜单点击“Internet选项”。 2&#xff0c;点击“隐私”选项&#xff0c;在页面中点击“高级”。…

5.Lambert光照Diffuse Shader

http://blog.csdn.net/candycat1992/article/details/17355629 这篇文章写的很好&#xff0c;这里就直接上代码了 Shader "Study/5_LambertDiffuse" {Properties{_Color("Main Color", Color) (1,1,1,1)_MainTex("Base (RGB)", 2D) "whit…

计算机用户的注册表,计算机上的注册表在哪里

注册表在哪里: 计算机中的注册表在哪里&#xff1f;疯狂代码&#xff1f;: http://CrazyCoder.cn/DeveloperUtil/Article31113.html“开始”→“运行”菜单项&#xff0c;在运行中输入regedit&#xff0c;然后按Enter打开注册表编辑器&#xff0c;逐一展开上述各项以获取注册表…

2017计算机应用技术考研,2017年中国科学技术大学081203计算机应用技术考研专业目录与考试科目.docx...

2017 年中国科学技术大学081203 计算机应用技术考研专业目录及考试科目081203 计算机应用技术1401、计算机网络应用技术李晓风① 101 思想政治理论&#xff1b;② 201谭海波英语一&#xff1b; ③ 301 数学一&#xff1b;④ 40802、计算机视觉张 龙计算机学科专业基础综合03、遥…

6.Half Lambert光照Diffuse Shader

简单来说&#xff0c;Lambert定律认为&#xff0c;在平面某点漫反射光的光强与该反射点的法向量和入射光角度的余弦值成正比&#xff08;即我们之前使用dot函数得到的结果&#xff09;。Half Lambert最初是由Valve&#xff08;游戏半条命2使用的引擎即是其开发的&#xff09;提…