游戏数据的处理方法、装置、电子设备及可读存储介质与流程

文档序号:17587813发布日期:2019-05-03 21:29阅读:345来源:国知局
游戏数据的处理方法、装置、电子设备及可读存储介质与流程

本发明涉及数据处理技术领域,具体而言,本发明涉及一种游戏数据的处理方法、装置、电子设备及可读存储介质。



背景技术:

随着用户对游戏品质需求的提升,mmorpg(massivemultiplayeronlinerole-playinggame,大型多人在线角色扮演游戏)作为网络游戏中最重要的一种类型,也在潮流中不断的进化着。目前,mmorpg已经基本进入3d(3dimensions,三维)时代,3d游戏的玩法不仅仅在地面,玩家可以在游戏中进行空中飞行、战斗等等。

目前3d游戏通常有三种做法:一种是体素(voxel),体素是3d空间的最小表示单位,类比于2d空间的像素;一种是多边形网格,该方式的缺点是查找效率较低,后台性能压力大;再一种是分层即多层网格,但该方式的缺点是地面以上很难划分层的界线,对于复杂建筑,在建筑层数较多时,如果完整的表示,需要大量阻挡图,内存占用太大。

对于体素而言,在目前现有相关技术中,体素也因占用存储空间过大,导致难以普及。如何优化体素占用的存储空间,是推广体素应用急需解决的重要问题之一。



技术实现要素:

针对现有技术中存在的至少一个技术问题,本发明提供了一种游戏数据的处理方法、装置、电子设备及可读存储介质,以优化游戏数据对存储空间的占用。为了实现该目的,本发明实施例提供的技术方案如下:

第一方面,本发明实施例提供了一种游戏数据的处理方法,其中,游戏场景中的场景对象由至少一个体素构成,每个体素为一个长方体,每个体素的体素信息包括对应的长方体的上表面高度和下表面高度;该方法包括:

生成游戏场景中的体素;

将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中;

其中,每个水平位置为游戏地图中水平面上的一块区域,每块区域的形状和大小为体素的上表面或下表面的形状和大小,垂直投影在同一水平位置上的体素为同一水平位置处的体素,每个水平位置处的第一个体素为上表面高度最小的体素。

第一方面的可选实施方式中,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中,包括:

按照预配置的水平位置之间的存储顺序,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中。第一方面的可选实施方式中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中,包括:

将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中。

第一方面的可选实施方式中,若相邻的至少两个水平位置处的体素信息相同,将每个水平位置处的体素信息存储到一维的第一数组中,包括:

只将相邻的至少两个水平位置处中的一个水平位置处的体素信息存储到第一数组中,并在第一数组中设置与一个水平位置对应的第一标记,第一标记用于标识相邻的至少两个水平位置处的体素信息相同。

第一方面的可选实施方式中,生成游戏场景中的体素,包括:

生成游戏场景中的原体素;

将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,合并条件包括:

位于同一水平位置处且高度差小于设定高度的相邻的原体素,和/或,封闭的场景对象的同一水平位置处的原体素;

其中,高度差是指相邻的原体素中高度较大的原体素的下表面与高度较小的原体素的上表面的高度差,合并后的体素的上表面高度为合并前高度较大的原体素的上表面高度,合并后的体素的下表面高度为合并前高度较小的原体素的下表面高度。

第一方面的可选实施方式中,将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,包括:

对于每一个水平位置处的原体素,若相邻的原体素之间的高度差不小于所述设定高度,则生成一个反体素;

其中,反体素的上表面为相邻的原体素中高度较大的原体素的下表面,反体素的下表面为相邻的原体素中高度较小的原体素的上表面;

确定所生成的所有反体素中的连通反体素;

其中,连通反体素是指与邻居反体素的交集高度差不小于所述设定高度的反体素,交集高度差是指两个反体素中高度较小的反体素的上表面高度与高度较大的反体素的下表面高度的差值,一个反体素的邻居反体素是指该反体素所在的水平位置的相邻水平位置处的反体素;

将所有连通反体素作为原体素,生成新的反体素,新的反体素为游戏场景中的体素。

第一方面的可选实施方式中,若游戏场景中的场景对象下方悬空,该方法还包括:

在场景对象下方距离场景最低可达高度第一设定距离的位置生成指定对象的体素,其中,指定对象的体素的体素信息不包括下表面高度,指定对象在游戏场景中不显示。

第一方面的可选实施方式中,该方法还包括:

配置游戏场景中的玩家实际活动区域边界,其中,玩家实际活动区域的下边界位于游戏地图下边界以下第二设定距离处,第二设定距离不小于第一设定距离,游戏地图下边界的高度不大于场景最低可达高度;

在游戏地图下边界下方的第一设定距离处生成指定对象的体素。

第一方面的可选实施方式中,场景对象不包括水,若游戏场景中存在水,该方法还包括:

将游戏地图划分为多个地图块,并设置每个地图块的标识;

根据存在水的地图块的个数,创建相应个数的二维的第三数组,每个第三数组用于存储对应的存在水的地图块中的每个水平位置处的水的高度;

创建二维的第一指针数组,其中,第一指针数组的指针元素个数为所有地图块的个数,第一指针数组中的元素索引为地图块的标识,若地图块中不存在水,则对应的指针元素为设定值,若地图块中存在水,则对应的指针元素为地图块对应的第三数组的存储位置。

第一方面的可选实施方式中,该方法还包括:

设置每个体素的第二标记,每个体素的第二标记用于标识八方向中每个方向上该体素的相邻体素是否可行走。

第二方面,本发明实施例提供了一种基于第一方面或第一方面任一可选实施方式中所示的方法的一种游戏数据的处理方法,该方法包括:

获取待加载游戏场景中的场景资源数据,场景资源数据包括待加载游戏场景中所有体素的体素信息;

在内存中创建一维的第四数组和一维的第五数组;

将待加载游戏场景中的每个水平位置处的所有体素信息加载到第四数组中,将每个水平位置处的体素信息在第四数组中的位置加载到第五数组中。

第二方面的可选实施方式中,若待加载游戏场景中存在水域,场景资源数据还包括存在水的地图块中的每个水平位置处的水的高度,方法还包括:

根据存在水的地图块的个数,创建相应个数的二维的第六数组;

将每个地图块中的每个水平位置处的水的高度加载到对应的第六数组中;

创建二维的第二指针数组,指针数组的元素个数为游戏地图被划分成的所有地图块的个数,每个指针元素对应一个地图块,对于不存在水的地图块,第二指针数组中对应的指针元素为设定值,对于存在水的地图块,第二指针数组中对应的指针元素为地图块对应的第六数组的存储位置。

第二方面的可选实施方式中,若方法的执行主体为客户端,待加载游戏场景为客户端对应的玩家角色当前所在的游戏场景,该方法还包括:

根据所加载的体素信息的上表面网格mesh生成第一navmesh(导航网格);

基于预配置的第一扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第一navmesh行走到的体素确定为第一地面体素,第一地面体素的高度作为待加载游戏场景的地面高度;

确定每个第一地面体素的上表面mesh的优先级,并设置每个第一地面体素的上表面mesh的优先级标记,其中,若第一地面体素所在的水平位置的可行走区域的半径大于设定值,则第一地面体素的上表面mesh为第一优先级,否则为第二优先级,第一优先级高于第二优先级;

根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,其中,存在第二navmesh的区域为待加载游戏场景中的可行走区域;

若方法的执行主体为服务器,待加载游戏场景为所有游戏场景,该方法还包括:

根据所加载的体素信息的上表面网格mesh生成第三navmesh;

基于预配置的第二扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第二navmesh行走到的体素确定为第二地面体素,第二地面体素的高度作待加载游戏场景的地面高度;

基于第二地面体素的上表面网格mesh生成第四navmesh;

将存在第四navmesh的区域作为可行走区域,不存在第四navmesh的区域作为不可行走区域,生成阻挡图,阻挡图用于标识哪些场景中哪些区域可行走。

第二方面的可选实施方式中,根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,包括:

生成待加载游戏场景的多边形mesh,其中,多边形mesh的高度小于体素的上表面mesh,多边形mesh的优先级低于体素的上表面mesh的优先级;

根据带优先级标记的第一地面体素的上表面mesh以及多边形mesh,生成带优先级标记的第二navmesh。

第二方面的可选实施方式中,该方法还包括:

接收到玩家角色的移动请求时,根据玩家角色的当前位置、移动请求所对应的移动方向和预配置的时间间隔,确定玩家角色的目标位置,移动请求为行走请求或飞行请求;

根据移动路径上的体素信息,基于预配置的碰撞检测条件,对玩家角色的目标位置进行碰撞检测,其中,移动路径是基于第二navmesh确定的由玩家角色的当前位置到玩家角色的目标位置之间的路径;

根据碰撞检测结果确定玩家角色的最终位置,根据玩家角色的最终位置控制玩家的移动。

第二方面的可选实施方式中,在玩家角色的最终位置不是玩家当前位置时,该方法还包括:

确定摄像机的目标位置;

检测摄像机的目标位置是否在体素内,或者,摄像机的当前位置和摄像机的目标位置之间是否存在体素阻挡;

若摄像机的目标位置在体素内,或者,摄像机的当前位置和摄像机的目标位置之间存在体素阻挡时,则将摄像机移动到射线与阻挡对应的体素的第一个交点的位置上,其中,射线的起点为玩家最终位置,射线的终点为摄像机的目标位置。

第三方面,本发明提供了一种游戏数据的处理装置,该装置包括:

体素生成模块,用于生成游戏场景中的体素,游戏场景中的场景对象由至少一个体素构成,每个体素为一个长方体,每个体素的体素信息包括对应的长方体的上表面高度和下表面高度;

体素存储模块,用于将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中;

其中,每个水平位置为游戏地图中水平面上的一块区域,每块区域的形状和大小为体素的上表面或下表面的形状和大小,垂直投影在同一水平位置上的体素为同一水平位置处的体素,每个水平位置处的第一个体素为上表面高度最小的体素。

第三方面的可选实施方式中,体素存储模块可以具体用于:

按照预配置的水平位置之间的存储顺序,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中。

第三方面的可选实施方式中,体素存储模块在将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中时,可以具体用于:

将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中。

第三方面的可选实施方式中,若相邻的至少两个水平位置处的体素信息相同,体素存储模块再将每个水平位置处的体素信息存储到一维的第一数组中时,具体用于:

只将相邻的至少两个水平位置处中的一个水平位置处的体素信息存储到第一数组中,并在第一数组中设置与一个水平位置对应的第一标记,第一标记用于标识相邻的至少两个水平位置处的体素信息相同。

第三方面的可选实施方式中,体素生成模块包括:

原体素生成单元,用于生成游戏场景中的原体素;

体素合并单元,用于将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,合并条件包括:

位于同一水平位置处且高度差小于设定高度的相邻的原体素,和/或,封闭的场景对象的同一水平位置处的原体素;

其中,高度差是指相邻的原体素中高度较大的原体素的下表面与高度较小的原体素的上表面的高度差,合并后的体素的上表面高度为合并前高度较大的原体素的上表面高度,合并后的体素的下表面高度为合并前高度较小的原体素的下表面高度。

第三方面的可选实施方式中,体素合并单元具体用于:

对于每一个水平位置处的原体素,若相邻的原体素之间的高度差不小于设定高度,则生成一个反体素;

其中,反体素的上表面为相邻的原体素中高度较大的原体素的下表面,反体素的下表面为相邻的原体素中高度较小的原体素的上表面;

确定所生成的所有反体素中的连通反体素;

其中,连通反体素是指与邻居反体素的交集高度差不小于设定高度的反体素,交集高度差是指两个反体素中高度较小的反体素的上表面高度与高度较大的反体素的下表面高度的差值,一个反体素的邻居反体素是指该反体素所在的水平位置的相邻水平位置处的反体素;

将所有连通反体素作为原体素,生成新的反体素,新的反体素为游戏场景中的体素。

第三方面的可选实施方式中,若游戏场景中的场景对象下方悬空,该装置还包括:

第一指定体素生成模块,用于在场景对象下方距离场景最低可达高度第一设定距离的位置生成指定对象的体素,其中,指定对象的体素的体素信息不包括下表面高度,指定对象在游戏场景中不显示。

第三方面的可选实施方式中,该装置还包括:

实际活动边界配置模块,用于配置游戏场景中的玩家实际活动区域边界,其中,玩家实际活动区域的下边界位于游戏地图下边界以下第二设定距离处,第二设定距离不小于第一设定距离,游戏地图下边界的高度不大于场景最低可达高度;

第二指定体素生成模块,用于在游戏地图下边界下方的第一设定距离处生成指定对象的体素。

第三方面的可选实施方式中,场景对象不包括水,若游戏场景中存在水,该装置还包括:

地图划分模块,用于将游戏地图划分为多个地图块,并设置每个地图块的标识;

水数据存储模块,用于根据存在水的地图块的个数,创建相应个数的二维的第三数组,每个第三数组用于存储对应的存在水的地图块中的每个水平位置处的水的高度;以及用于创建二维的第一指针数组,其中,第一指针数组的指针元素个数为所有地图块的个数,第一指针数组中的元素索引为地图块的标识,若地图块中不存在水,则对应的指针元素为设定值,若地图块中存在水,则对应的指针元素为地图块对应的第三数组的存储位置。

第三方面的可选实施方式中,该装置还包括:

可行走标识设置模块,用于设置每个体素的第二标记,每个体素的第二标记用于标识八方向中每个方向上该体素的相邻体素是否可行走。

第四方面,本发明提供了一种游戏数据的处理装置,该装置包括:

资源数据获取模块,用于获取待加载游戏场景中的场景资源数据,场景资源数据包括待加载游戏场景中所有体素的体素信息;

数据加载模块,用于在内存中创建一维的第四数组和一维的第五数组,将待加载游戏场景中的每个水平位置处的所有体素信息加载到第四数组中,将每个水平位置处的体素信息在第四数组中的位置加载到第五数组中。

第四方面的可选实施方式中,若待加载游戏场景中存在水域,场景资源数据还包括存在水的地图块中的每个水平位置处的水的高度,该装置还包括水资源数据加载模块,水资源数据加载模块用于:

根据存在水的地图块的个数,创建相应个数的二维的第六数组;

将每个地图块中的每个水平位置处的水的高度加载到对应的第六数组中;

创建二维的第二指针数组,指针数组的元素个数为游戏地图被划分成的所有地图块的个数,每个指针元素对应一个地图块,对于不存在水的地图块,第二指针数组中对应的指针元素为设定值,对于存在水的地图块,第二指针数组中对应的指针元素为地图块对应的第六数组的存储位置。

第四方面的可选实施方式中,若该客户端为客户端装置,待加载游戏场景为客户端对应的玩家角色当前所在的游戏场景,该装置还包括导航网格生成模块,该模块用于:

根据所加载的体素信息的上表面网格mesh生成第一navmesh;

基于预配置的第一扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第一navmesh行走到的体素确定为第一地面体素,第一地面体素的高度作为待加载游戏场景的地面高度;

确定每个第一地面体素的上表面mesh的优先级,并设置每个第一地面体素的上表面mesh的优先级标记,其中,若第一地面体素所在的水平位置的可行走区域的半径大于设定值,则第一地面体素的上表面mesh为第一优先级,否则为第二优先级,第一优先级高于第二优先级;

根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,其中,存在第二navmesh的区域为待加载游戏场景中的可行走区域;

若该装置为服务器中的装置,待加载游戏场景为所有游戏场景,该装置还包括阻挡图生成模块,该模块用于:

根据所加载的体素信息的上表面网格mesh生成第三navmesh;

基于预配置的第二扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第二navmesh行走到的体素确定为第二地面体素,第二地面体素的高度作为待加载游戏场景的地面高度;

基于第二地面体素的上表面网格mesh生成第四navmesh;

将存在第四navmesh的区域作为可行走区域,不存在第四navmesh的区域作为不可行走区域,生成阻挡图,阻挡图用于标识哪些场景中哪些区域可行走。

第四方面的可选实施方式中,导航网格生成模块在根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh时,具体用于:

生成待加载游戏场景的多边形mesh,其中,多边形mesh的高度小于体素的上表面mesh,多边形mesh的优先级低于体素的上表面mesh的优先级;

根据带优先级标记的第一地面体素的上表面mesh以及多边形mesh,生成带优先级标记的第二navmesh。

第四方面的可选实施方式中,该装置还包括玩家位置控制模块,玩家位置控制模块用于:

接收到玩家角色的移动请求时,根据玩家角色的当前位置、移动请求所对应的移动方向和预配置的时间间隔,确定玩家角色的目标位置,移动请求为行走请求或飞行请求;

根据移动路径上的体素信息,基于预配置的碰撞检测条件,对玩家角色的目标位置进行碰撞检测,其中,移动路径是基于第二navmesh确定的由玩家角色的当前位置到玩家角色的目标位置之间的路径;

根据碰撞检测结果确定玩家角色的最终位置,根据玩家角色的最终位置控制玩家的移动。

第四方面的可选实施方式中,在玩家角色的最终位置不是玩家当前位置时,该装置还包括摄像机位置确定模块,摄像机位置确定模块用于:

确定摄像机的目标位置;

检测摄像机的目标位置是否在体素内,或者,摄像机的当前位置和摄像机的目标位置之间是否存在体素阻挡;

若摄像机的目标位置在体素内,或者,摄像机的当前位置和摄像机的目标位置之间存在体素阻挡时,则将摄像机移动到射线与阻挡对应的体素的第一个交点的位置上,其中,射线的起点为玩家最终位置,射线的终点为摄像机的目标位置。

第五方面,本发明提供了一种电子设备,该电子设备包括处理器和存储器;

存储器中存储有可读指令,可读指令由处理器加载并执行时,实现本发明实施例第一方面、第一方面的任一可选实施方式、第二方面或第二方面的任一可选实施方式中所示的方法。

第六方面,本发明提供了一种计算机可读存储介质,该存储介质中存储有可读指令,可读指令由处理器加载并执行时,实现本发明实施例第一方面、第一方面的任一可选实施方式、第二方面或第二方面的任一可选实施方式中所示的方法。

本发明实施例提供的技术方案带来的有益效果是:本发明实施例所提供的方案,通过体素来表示游戏场景中的场景对象,对于体素信息的存储,采用两个一维数组(即上述第一数组和第二数组)来实现,采用该种数据存储方式,能够有效减少体素信息所占用的存储空间,且在将体素信息加载到内存中时,能够避免大量的new操作和空间不连续造成的存储碎片及cachemiss的问题。另外,基于本发明实施例提供的方案,能够有效降低体素信息查找的时间复杂度。

附图说明

为了更清楚地说明本发明实施例中的技术方案,下面将对本发明实施例描述中所需要使用的附图作简单地介绍。

图1示出了本发明一个可选实施例中提供的一种游戏数据的处理方法的整体方案示意图;

图2示出了本发明一个实施例中提供的一种游戏数据的处理方法的流程示意图;

图3示出了本发明一示例中汽车的体素模型的示意图;

图4示出了本发明一示例中三维坐标的示意图;

图5示出了本发明一示例中同一水平位置处的两个体素的示意图;

图6a示出了本发明一示例中的游戏场景的示意图;

图6b示出了图6a中的场景对象的体素模型的示意图;

图6c示出了将图6b中的体素进行合并后的体素模型的示意图;

图7示出了本发明另一示例中的游戏场景的示意图;

图8a示出了本发明又一示例中的游戏场景的示意图;

图8b示出了图8a中的场景对象的一种体素模型的示意图;

图8c示出了图8a中的场景对象的另一种体素模型的示意图;

图9示出了本发明一示例中玩家实际活动区域的示意图;

图10示出了本发明一示例中的地图块的示意图;

图11示出了本发明另一实施例中提供的一种游戏数据的处理方法的流程示意图;

图12示出了本发明一示例中的场景中的navmesh的示意图;

图13示出了本发明另一示例中的场景中的navmesh的示意图;

图14示出了本发明再一示例中的场景中的navmesh的示意图;

图15示出了本发明一示例中玩家贴墙移动时的移动路径示意图;

图16示出了本发明一示例中的场景中的一种navmesh的示意图;

图17示出了图16中所示的场景中的另一种navmesh的示意图;

图18中示出了本发明一示例中游戏场景中的房顶的示意图;

图19中示出了图18中所示的房顶的体素的navmesh的示意图;

图20示出了一种二维的bresenham算法的实施方式示意图;

图21示出了本发明一实施例提供的一种游戏数据的处理装置的结构示意图;

图22示出了本本发明另一实施例提供的一种游戏数据的处理装置的结构示意图;

图23中示出了本发明实施例中提供的一种电子设备的结构示意图。

具体实施方式

为使得本发明的发明目的、特征、优点能够更加的明显和易懂,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而非全部实施例。基于本发明中的实施例,本领域技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。

下面详细描述本发明的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,仅用于解释本发明,而不能解释为对本发明的限制。

本技术领域技术人员可以理解,除非特意声明,这里使用的单数形式“一”、“一个”、“所述”和“该”也可包括复数形式。应该进一步理解的是,本发明的说明书中使用的措辞“包括”是指存在所述特征、整数、步骤、操作、元件和/或组件,但是并不排除存在或添加一个或多个其他特征、整数、步骤、操作、元件、组件和/或它们的组。应该理解,当我们称元件被“连接”或“耦接”到另一元件时,它可以直接连接或耦接到其他元件,或者也可以存在中间元件。此外,这里使用的“连接”或“耦接”可以包括无线连接或无线耦接。这里使用的措辞“和/或”包括一个或更多个相关联的列出项的全部或任一单元和全部组合。

下面以具体地实施例对本发明的技术方案以及本发明的技术方案如何解决上述技术问题进行详细说明。下面这几个具体的实施例可以相互结合,对于相同或相似的概念或过程可能在某些实施例中不再赘述。下面将结合附图,对本发明的实施例进行描述。

体素是3d空间的最小表示单位,体素的概念是从二维空间的最小单位像素衍伸而来,像素用于描述二维的影像,而体素则可以用于描述三维空间上的立体的对象,是三维空间分割上的最小单位,在游戏中可用于行走、飞行、摄像机等碰撞检测,但在现有技术中,体素因内存过大而难以普及。

针对现有技术中所存在的问题,本发明实施例所提供的方案,致力于体素的存储空间的优化,包括体素内存、性能的优化,该方案适用于前端(客户端)和后台(服务器)。

图1中示出了本发明一个可选实施例中提供的一种游戏数据的处理方法的整体方案示意图,如图中所示,该方法在生成体素后,通过体素合并、地面处理、水处理、范围控制、内存自管理优化内存,然后再通过预先计算体素之间可达优化效率,实现了对基于体素实现的游戏数据的优化处理。在体素体系下,本发明的实施例还进一步提供了获取地面高度(图中所示的地面高度)、生成后台阻挡图(图中所示的后台阻挡)、前台生成优先级navmesh(navigationmesh,导航网格)、锯齿平滑处理(图中所示的锯齿)、行走、轻功、摄像机碰撞(图中所示的摄像机)等功能。后文中将对图1中所示的流程中的各部分内容进行详细说明。

图2示出了本发明实施例提供的一种游戏数据的处理方法,如图2中所示,该方法可以包括以下步骤:

步骤s110:生成游戏场景中的体素;

体素即为游戏场景对象中的场景对象的基本构成单元,每个场景对象由至少一个体素构成。场景对象即游戏场景的3d图像中的对象,如游戏场景中的建筑、地形、山、石头等等。

体素的具体生成方式可采用现有技术实现,在一可选方式中,可以基于开源项目recast实现,该项目由mesh(网格)经过体素化、地区生成、轮廓生成、多边形网格生成、高度细节生成等步骤生成navmesh,将recast对mesh体素化的代码抽出来即可生成体素。

本发明实施例中,每个体素为一个长方体,表示有实物占据了该长方体,场景对象的模型完全由长方体拼成,每个体素的体素信息包括对应的长方体的上表面高度和下表面高度。如图3中所示的一种汽车的体素模型,该汽车由大量的长方体拼成。

在实际应用中,长方体表面(上表面和下表面)的面积大小可以根据实际需求配置,在一可选方式中,长方体表面的长度和宽度可以相等,也就是,上下表面的形状为正方形,例如,上下表面的长度和宽度可以为0.5m(米)。

在实际应用中,场景对象中的树叶等不会阻挡玩家移动的场景对象,不生成体素。

步骤s120:将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中。

其中,每个水平位置为游戏地图中水平面上的一块区域,每块区域的形状和大小为体素的上表面或下表面的形状和大小,垂直投影在同一水平位置上的体素为同一水平位置处的体素,每个水平位置处的第一个体素(也可称为第一层体素)为该水平位置处的上表面高度最小的体素。

水平位置是在3d游戏场景中,是不考虑高度信息时的位置信息。如图4中所示的三维坐标的示意图,以z轴表示游戏场景中的高度信息,则x轴和y轴所形成的平面即为水平面,在体素的上下表面都是0.5*0.5的正方形时,则游戏地图中每个0.5*0.5的格子即为一个水平位置,如图中所示的多个格子,每个格子所在的位置为一个水平位置。如果一个水平位置(x,y)处(假设为图4中所示的p处)3m到4m和5m到10m均有实物,则(x,y)处对应有两个体素,第一个体素的上表面高度和下表面高度分别为4m和3m,第二个体素的上表面高度和下表面高度分别为10m和5m,例如以图5中所示的两个体素表示p处的两个体素,则这两个体素的垂直投影对应的同一水平位置,第一个体素占据p处上方3m到4m处,第二个体素占据p处上方5m到10m处,也就是说游戏场景中对应于两个体素的位置被场景对象或场景对象的部分占据。

作为一个示例,图6a示出了一种游戏场景中的部分场景的示意图,图6b示出了图6a中所示的场景中的场景对象的体素的示意图。由图6b可以看出,对于图6a的石头,该石头的体素模型完全由长方体拼成,该示例中每个长方体的上下表面均为正方形,长宽均为0.5m。

在实际应用中,地面的场景对象是最多的,因此,地面是每个游戏场景中存在体素最多的,然而地面的下表面高度并不需要,因为玩家不可能到地面以下,因此,地面体素(此时是将场景的第一层体素作为地面体素,即下表面高度为零的体素)的下表面高度并不需要存储,可以统一认为0。采用该方式,在将游戏安装到电子设备(可以是终端设备或服务器)中时,可以有效减少体素存储所占用的外存(如硬盘)的存储空间,在将体素信息加载到内存进行体素的渲染时,可以有效减少对内存的占用。例如,对于一个游戏地图面积为800m*800m的游戏场景,在长方体的上下表面的长和宽都是0.5m,一个高度值占2byte(字节)时,则可节省1600*1600*2byte的存储空间,即约为10m(兆字节)。

对于体素信息的存储,可以有以下三种方案:

第一种,地面体素信息全部存储,地面以上分块存储,因为地面以上体素较少,分块存储可省掉大部分没有体素的区域,然而该方案仍然有相当大的存储空间(磁盘和内存)的浪费,这是因为在采用分块存储时,需要指向每个块的指针,其次每个块内也有相当大的区域没有体素,但仍会占用存储空间。

第二种,采用四叉树的存储方式,该方案虽然不会给没有体素的区域开辟空间,然而体素的查找时间复杂度为o(logn),而且需要父节点到子节点的指针。

第三种,每个(x,y)即每个水平位置处都new出来一个数组,数组内存储(x,y)处所有体素信息,然而对于例如800m*800m的游戏场景,在长方体的上下表面的长和宽都是0.5m时,就需要new出来1600*1600个数组,即256万次new操作,此时指针所占空间为1600*1600*4byte,即为10m,如果使用unity,c#语言在64位机器上指针占8byte,则指针所占空间为20m,另外,如此多的new操作,必然带来大量磁盘碎片和内存碎片,而且查找(x,y)邻居的体素时会导致cachemiss(高速缓存未命中),因为(x,y)和(x,y)邻居的指针指向的空间在内存上并不连续。以上三种方案或多或少在存储空间(磁盘和内存)和性能上都有问题。

针对于上述多种存储方式所存在的问题,本发明实施例中,对于体素的存储,本发明实施例中,采用两个一维数组(即上述第一数组和第二数组)来实现,具体的,将游戏场景中的所有体素的体素信息存储到第一数组中,第二数组则用于存储每个水平位置处的体素信息在第一数组中的位置。采用该种数据存储方式,第一数组记录所有体素信息,第二数组记录每个水平位置在体素在第一数组中的位置,在将体素信息加载到内存中时,能够避免大量的new操作和空间不连续造成的存储碎片及cachemiss的问题。

另外,基于该存储方式进行某一水平位置处的体素查找时,由于体素信息是存储到第一数组中的,体素信息在第一数组中的位置是存储在第二数组中的,因此,可以基于第二数组中所存储的当前水平位置处的体素信息的位置,在第一数组中的相应位置,查到到所需要查找的体素的体素信息。基于本发明实施例的存储方式,可以大大降低体素查找时间的复杂度。

本发明的可选实施例中,上述步骤s120中,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中,包括:

按照预配置的水平位置之间的存储顺序,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中。

在实际应用中,在进行体素信息以及体素信息在第一数组中的位置的存储时,可以基于一定的存储顺序进行存储,以进一步提升每个水平位置处的体素的查找效率。

本发明的可选实施例中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中,包括:

将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中。

在进行体素信息的存储时,由于可以是以每个水平位置为单位进行的存储,也就是说,每个水平位置处的体素的体素信息是连续存储的,因此,为了减少存储空间的占用,可以只将每个水平位置处的体素信息在第一数组中的起始位置存储到第二数组中。

基于本发明实施例的该方案,在查找某一水平位置处的体素信息时,可以首先在第二数组中查找到当前水平位置处的体素信息在第一数组中的起始位置,以及当前水平位置的下一水平位置处(按照存储顺序的下一水平位置)的体素信息在第一数组中的起始位置,由于每个水平位置处的第一个体素的下表面高度不存储,因此,由下一水平位置对应的起始位置减去当前水平位置对应的起始位置再加一之后除以2,即可得出当前水平位置处的体素的个数,从而基于当前水平位置对应的起始位置和体素的个数,在第一数组中即可查找到当前水平位置处的所有体素的体素信息。可见,基于本发明实施例提供的该存储方式,可将体素的查找时间复杂度降为o(1)。

需要说明的是,上述存储顺序指的水平位置之间的存储顺序,例如,一种可选方式中,以x轴和y轴所形成的空间表示水平空间,存储顺序可以是以y轴方向的水平位置优先存储,具体的,以(x,y)表示第一个水平位置,则存储顺序为先将(x,y)处的所有体素信息依次存储到第一数组中,再将(x,y+1)、(x,y+2)、……、(x,y+n)处的所有体素信息依次存储到第一数组中,之后再将(x+1,y)、(x+1,y+2)、……、(x+1,y+n)处的所有体素信息依次存储到第一数组中,直至完成游戏场景中的所有体素信息的存储。而水平位置处的体素信息在第一数组中的起始位置,是指该水平位置处的第一个体素信息在第一数组中的起始位置。

作为一个示例,以下示出了一种体素生成工具将体素写进二进制文件的一种可选的代码实现方式:

具体的,该方案中,如上述代码所示,通过一个一维数组spanarr记录所有体素信息,spanarr的每个元素的数据类型为short类型,上述代码中smax和smin分别为每个体素上表面高度和下表面高度,因为体素高度以0.1m为粒度,如果short值为64,则代表高度为6.4m;上述代码中,row为水平长度,col为水平宽度,row*col即为场景大小,一个一维数组indexarr(即代码中所示的countarrr)记录(x,y)处的体素在spanarr中的位置count2;(x,y)处的体素存在链表中,链表头为m_solid->spans[x+y*row]。将场景中所有体素按顺序写入spanarr中,(x,y)处第一个体素,即index==0时,只写入上表面高度,非第一个体素上下表面高度smax和smin均写入。

在游戏中,一个一维数组m_spanarr记录所有体素信息,一个一维数组m_indexarr记录(x,y)处的体素在m_spanarr中的位置,查找(x,y)处的所有体素,具体的,首先查找在m_indexarr中查找(x,y)处体素在m_spanarr中的起始位置start和个数count,start即为m_indexarr在(x,y)处元素,count即为m_indexarr在(x,y+1)处元素减去在(x,y)处元素加一除以2,因为(x,y)处第一个体素不存下表面高度,假设(x,y)处有两个体素,第一个体素上下高度分别为4、3,第二个体素上下高度分别为10、7,则m_spanarr在(x,y)处会记录三个元素4、7、10,假设m_indexarr中(x,y)处体素在m_spanarr中的起始位置start为5,即(x,y)处的第一个体素的体素信息是m_spanarr中的第5个元素,则(x,y+1)处体素在m_spanarr中的起始位置start为8,因此(x,y)处体素数目为(3+1)/2,即为2。

接下来根据start和count在m_spanarr中找出(x,y)处所有体素,在一可选方式中,如下所示的代码:

该方式中,所有的上表面高度(smax)可以存在m_spanarr的ptr(指针)+start+i*2处,除了第一个体素,所有体素下表面高度存在m_spanarr的ptr+start+i*2-1处位置,根据确定处的start和count即可在m_spanarr中查找到(x,y)出的所有体素。其实这种存储方式,相当于将上文的第三种方式的指针自行管理,但避免了大量的new操作和空间不连续,以及cachemiss。

本发明所提供的图2中所示的方案,适用于游戏的研发生成阶段,采用该方案,在通过体素来表示游戏场景中的对象时,能够有效减少体素信息所占用的存储空间(包括电子设备的外存的存储空间以及运行游戏时所占用的内存空间),且能够有效降低体素信息查找的时间复杂度。

本发明的可选实施例中,若相邻的至少两个水平位置处的体素信息相同,将每个水平位置处的体素信息存储到一维的第一数组中,包括:

只将相邻的至少两个水平位置处中的一个水平位置处的体素信息存储到第一数组中,并在第一数组中设置与一个水平位置对应的第一标记,第一标记用于标识相邻的至少两个水平位置处的体素信息相同。

其中,该处的相邻指的是八方向相邻,即一个水平位置的八邻域位置。对于大多数水平位置而言,水平位置的相邻水平位置一般可以有八个,也就是八方向上的相邻的水平位置,对于边缘处的水平位置,相邻水平位置的个数则会减少,一般为3个。如对于图4中所示q所在的水平位置,其相邻水平位置则包括q1至q8这八个水平位置,对于q7所示的水平位置,如果q7为场景地图的边缘位置,则该位置的相邻水平位置则是q6、q8和q三个水平位置。对于一个水平位置(x,y),其八邻区的八个点坐标则为(x-1,y-1);(x,y-1);(x+1,y-1);(x-1,y);(x+1,y);(x-1,y+1);(x,y+1);(x+1,y+1),可以理解的时,坐标中的1对应于水平位置之间的相对位置关系,对于图4中所示的水平位置,若q的位置坐标为(x,y),则(x-1,y-1)则对应为q7的坐标。

两个水平位置处的体素信息相同,指的是两个水平位置处所包括的体素的个数相同,且高度上对应的体素的体素信息也相同。例如,一个水平位置的体素个数为2个,第一个体素的上表面高度为2m、下表面高度为0,第二个体素的上表面高度为5m,下表面高度为4m,若该水平位置的一个相邻水平位置处的体素信息与该位置的体素信息相同,则该相邻水平位置的体素的个数为两个,且第一个体素的上下表面高度为2m和0,第二个体素的上下表面高度为5m和4m。

在实际应用中,如果项目中场景不复杂,则可以采用该方式进一步进行存储优化。例如,水平位置(x,y)和(x,y+1)、(x+1,y)、(x+1,y+1)处均有k个体素,且k个体素的上下高度完全相同,则在第一数组存储(x,y)第一个体素时,加个第一标记(如该标记设置为真),以表示其三个邻居水平位置即相邻水平位置处的体素和(x,y)处相同,且(x,y+1)、(x+1,y)、(x+1,y+1)三个邻居的体素不写入第一数组。这样在查找(x+1,y)的体素时,首先查找(x,y)的第一个体素的标记,如果标记为真,表示(x+1,y)的体素和(x,y)完全相同,直接从第一数组取(x,y)的体素即可;如果标记为假,再采用前文中查找体素的方式,从第二数组中找(x+1,y)的体素在第一数组的起始位置和数量,然后在第一数组中取(x+1,y)的体素。在场景不复杂的情况下,采用该方式,体素信息对电子设备的外存和内存的占用会有显著减小。

本发明的可选实施例中,步骤s110中,生成游戏场景中的体素,具体可以包括:

生成游戏场景中的原体素;

将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,合并条件包括:

位于同一水平位置处且高度差小于设定高度的相邻的原体素,和/或,封闭的(即游戏角色无法进入到对象内部)场景对象的同一水平位置处的原体素;

其中,高度差是指相邻的原体素中高度较大的原体素的下表面与高度较小的原体素的上表面的高度差,合并后的体素的上表面高度为合并前高度较大的原体素的上表面高度,合并后的体素的下表面高度为合并前高度较小的原体素的下表面高度。

具体的,原体素是指通过体素生成工具生成的初始的体素。该方案中,在生成体素时,通过对原体素中符合合并条件的原体素进行合并,可进一步减少体素所占用的存储空间。

作为一个示例,假设在(x,y)处有两个体素(原体素),第一个体素上、下表面高度分别为4m、3m;第二个体素上、下表面高度分别为10m、5m。第一个体素的上表面和第二个体素的下表面之间的空间为1m,而假设人物身高(对应于上述设定高度)为1.8m,因此,该空间无法使人通过,这两个体素可以合并成一个体素,合并后的体素的上下表面高度分别为10m、3m。如果上述第二个体素下表面高度为6m,第一个体素的上表面和第二个体素的下表面之间的空间为2m,可以使人通过,因此不需要合并。在实际应用中,将该方式应用于秦时明月游戏中的蜃楼场景时,可以将蜃楼场景的体素大小从13.1m降到10.1m。

在游戏场景中,虽然很多模型是封闭的,但因为mesh(网格)只覆盖表面,生成的原体素也是空心的。例如,对于图6a所示的石头,该石头虽然是封闭的,但生成的原体素是空心的,如图6b中所示,石头的上下表面会分别用两个体素表示;再例如,如图7中所示的带有基座的建筑,建筑的基座下面虽然是玩家不可进去的,但基座内部和外部是连通的,这样通过体素生成工具生成基座的体素时,基座的内部和外部也都会分别生成体素,基座生成的体素也会是空心的,会造成存储空间的浪费。

但石头内部或基座内部是游戏玩家无法进去的空间,因此,可以将用于表示该种场景对象的同一水平位置上的体素进行合并,如用于表示石头的上下表面的两个体素可以合并成一个,因为人物无法进入石头内部。在实际应用中,通过连通区搜索,可以标记出石头内部和外部不连通,不连通区域的上下表面体素可以合并,通过该方式将石头或其他内部玩家角色无法进入的对象的体素合并成实心的。例如,对图6b中所示的用于表示石头的上下表面的部分体素进行合并,合并后的体素如图6c中所示,对于图6c中的箭头所指的部分体素,则是合并后的体素,可见,采用该合并方式,可以将石头的上下表面的两个体素合并为一个体素,通过该方式,可有效较少体素的个数,从而减少了需要存储的体素信息的数据量。

在实际应用中,通过这种体素合并的方式可以将上述蜃楼的体素大小从10.1m降到9.2m。采用该方式时,需要对美术有个要求:所有玩家进不去的空间,都做成封闭的,这样连通区搜索才能判定玩家进不去的空间是封闭的。

本发明的可选实施例中,将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,具体可以包括:

对于每一个水平位置处的原体素,若相邻的原体素之间的高度差不小于设定高度,则生成一个反体素;其中,反体素的上表面为相邻的原体素中高度较大的原体素的下表面,反体素的下表面为相邻的原体素中高度较小的原体素的上表面;

确定所生成的所有反体素中的连通反体素;其中,连通反体素是指与邻居反体素的交集高度差不小于设定高度的反体素,交集高度差是指两个反体素中高度较小的反体素的上表面高度与高度较大的反体素的下表面高度的差值,一个反体素的邻居反体素是指该反体素所在的水平位置的相邻水平位置处的反体素;

将所有连通反体素作为原体素,生成新的反体素,新的反体素为游戏场景中的体素。

具体的,也就是说,反体素的上表面高度为相邻的原体素中高度较大的原体素的下表面高度,反体素的下表面高度为相邻的原体素中高度较小的原体素的上表面高度。交集高度差则是指一个反体素与该反体素的邻居反体素的体素信息中,高度较小的反体素的上表面高度与高度较大的反体素的下表面高度的差值。

该方案提供的一种将体素合并的具体实现方式。对于该方案,作为一个具体实施可选方式,可以包括:

将所有原体素的体素信息记录到原体素集合中;

对于每一个水平位置处的原体素,若相邻的原体素之间的高度差不小于设定高度,则生成一个反体素,并将每个水平位置处的反体素的体素信息记录到反体素集合中;

确定反体素集合中的连通反体素;

删除反体素集合中的非连通反体素,得到新的反体素集合;

将新的反体素集合中的反体素作为原体素,生成新的反体素,新的反体素为游戏场景中的体素。

在进行体素合并时,一种可选方式可以是:首先选择一个种子点(原体素),然后通过种子点向前、后、左、右扩散,无法扩散到的空间,即为不连通的,需要被合并上下表面体素。在实现层面,直观的想法是构造一个三维矩阵,然后在三维矩阵里宽度优先搜索(深度优先一定会栈溢出),对于一个800m*800m*400m的场景,其中,800m*800m为水平面面积,400m为场景的高度,若体素的精度是长、宽为0.5m,高为0.1m,三维矩阵大小则为1600*1600*4000,内存占10g,宽度搜索一次需要20min(分钟)完成,那么生成18个场景的体素就需要6h,该种效率是实际应用中无法接受。基于此,本发明实施例提供了上述体素合并的方式,基于该方式,可以大大提高搜索效率,对于上述需要20min完成一次搜索的场景,采用该方案可以在1s内完成搜索。

具体的,该方案首先构建原体素的反体素,原体素表示有被实物占据的空间,反体素则表示没有被实物占据的空间。在一种可选方式中,对于反体素的构建,可以通过以下代码实现:

其中,m_solid->spans表示体素集合,记录场景的体素的集合,m_solid->antispans表示反体素结合,记录场景的反体素的集合,m_solid->spans[x+y*w]为一个链表头,指向链表中的第一个元素,该链表存(x,y)处所有体素,以height表示整个场景中的最高飞行高度,如果m_solid->spans[x+y*w]为空,则表示(x,y)处没有体素,则该位置以上没有实物,因此(x,y)处的反体素只有一个,上下表面高度分别为height、0。以lastmax记录(x,y)处上一个被遍历体素的上表面高度,如果下一个被遍历体素的下表面高度smin和lastmax之差大于人的高度,则可以在(x,y)处加一个反体素,上下表面高度分别为smin、lastmax,否则无需加入反体素,因为没有被实物占据的空间高度小于人的高度,人无法通过,这样就实现了合并间隙小于人高度的体素。以m_solid->ch表示体素高度的粒度,项目中采用0.1m,user_height为1.8m;如果遍历到最后一个体素,场景最高飞行高度height和lastmax的差值大于人的高度,则在(x,y)处加入一个反体素,上下表面高度分别为height、lastmax。

采用上述方式在完成所有反体素的生成后,需要标记连通区,即确定反体素集合中的连通反体素。继续以上述生成反体素的可选方案为例,连通区的标记可以通过以下代码实现:

具体的,在反体素集合antispans中可以采用宽度优先搜索,首先在myqueue中放入一个可行走区上方的反体素,从该反体素开始标记整个场景的连通反体素。首先从前、后、左、右四个方向遍历邻居(newx,newy),找出当前反体素frontspan和邻居反体素s的交集(min,max)即交集高度差,如果max和min之差高于人的高度,则表示可以从frontspan到达s,将反体素的标记flag标记为1,表示连通,并将s压入队列,直到队列为空,则标记完所有连通区。

完成所有反体素的标记后,在反体素集合antispans中删除所有flag标记为0的非连通区,一种可选的代码实现如下:

如果flag为0,并且pre为null,则表示(x,y)处第一个体素即为非连通区,则将表头后移,如果pre不为null,则从链表中删除该反体素。最后需要根据反体素集合antispans重新构建体素集合spans,通过这种方式,对于上述800m*800m*400m的场景的示例,该合并体素的方式,可使内存占用降低为10m左右,体素的搜索时间在1s之内。

本发明的可选实施例中,若游戏场景中的场景对象下方悬空,方法还包括:

在场景对象下方距离场景最低可达高度第一设定距离的位置生成指定对象的体素,其中,指定对象的体素的体素信息不包括下表面高度,指定对象在游戏场景中不显示。

由前文描述可知,在存储体素信息时,将场景的第一个体素认为是地面体素,然而在实际应用中总有例外,游戏场景中有的建筑的边沿下没有地面,因此会认为建筑边沿的下表面高度为0,这样玩家则无法飞到建筑边沿下,会感觉诡异,造成玩家体验较差。

如图8a中所示的游戏场景中,走廊建筑下有一部分是悬空,下面没有地面,该部分生成的体素因为省略掉下表面高度,统一认为下表面高度为0,则生成的体素如图8b所示,建筑下完全被体素挡住,建筑下的石头玩家也无法飞行过去。针对该问题,本方案,在场景最低可达高度之下设定距离处(1m)位置,加一个指定对象(可称为小片),为该小片生成体素,但在场景中不显示,该小片生成的体素没有下表面高度,此时,建筑边沿因为不是第一层体素,因此有了下表面高度,同时又因为该片在最低可到高度以下,因此玩家也无法到达该片。采用加小片的方式,新生成的体素如图8c所示,建筑下虽然没有地面,但体素生成正常,玩家则可以到达建筑下的石头上。

本发明的可选实施例中,该方法还可以包括:

配置游戏场景中的玩家实际活动区域边界,其中,玩家实际活动区域的下边界位于游戏地图下边界以下第二设定距离处,第二设定距离不小于第一设定距离,游戏地图下边界的高度不大于场景最低可达高度;

在游戏地图下边界下方的第一设定距离处生成所述指定对象的体素。

在实际应用中,虽然很多游戏场景的区域很大,但玩家的实际活动区域并没有那么大,如图9中所示的一游戏场景中,箭头1所指的虚线所围成的区域为场景大小800m*800m,箭头2所指的实线所围成的区域为允许玩家实际活动区域,大约为500m*500m,因为玩家无法到实际活动区域以外,因此,对于客户端而言,实际活动区域以外无需生成体素,也就是说,实际活动区域的边界限制了地图边界,地图的前、后、左、右、上边界是实际活动区域规定的边界,但向下边界需要比黄色边界高出第二设定距离(如可以为2m),这是因为实际活动区域的下边界以下都不生成体素,为了防止前文中所描述的建筑悬空、建筑以下被遮挡的情况出现,需要在实际活动区域的下边界以上第一设定距离(1m)的位置加小片,该小片生成体素,但为了防止玩家落到小片上,需要地图的下边界比小片略高,因此地图下边界比实际活动区域的下边界高,且高出的第二设定距离要大于第一设定距离,以使在出现建筑悬空时,游戏玩家能够到达悬空区域的场景对象,且不对跌落至小片上。采用该方案,如果实际活动区域以下地形复杂,因为实际活动区域以下可以不生成体素,从而客户端也可省掉一部分内存。

本发明的可选实施例中,上述场景对象可以不包括水,若游戏场景中存在水,该方法还包括:

将游戏地图划分为多个地图块;

根据存在水的地图块的个数,创建相应个数的二维的第三数组,每个第三数组用于存储对应的存在水的地图块中的每个水平位置处的水的高度;

创建二维的第一指针数组,其中,第一指针数组的元素个数为所有地图块的个数,第一指针数组中的元素索引为地图块的标识,若地图块中不存在水,则对应的指针元素为设定值,若地图块中存在水,则对应的指针元素为地图块对应的第三数组的存储位置。

在有些游戏场景中会有水域,也就是存在水,如在秦时明月项目中,镜湖场景有一半都是水,蜃楼场景也有几块面积几十平米的水域,那是否需要为水生成体素,如果生成体素,则需要标记该体素为水,每个体素就多带一个标记,然而由于只有个别场景有水,如果为所有场景的体素均加一个标记,并不合理。

为了解决上述问题,本方案中,可以对水并不生成体素,水的高度可以单独记录。在一种方式中,最直观的做法是对于游戏场景,开辟二维数组,每个水平位置(x,y)处记录水的高度,如果场景没有水,则不开辟该二维数组,如果用这种方式,游戏场景一般只有几块区域是水域(如对于秦时明月项目中的蜃楼场景只有几块面积几十平米的水域),如果通过二维数组对游戏场景中所有区域(不论是否为水域)的每个水平位置处都记录水的高度,则会造成极大的存储空间的浪费。例如,对于800m*800m的游戏场景,如果每个水平位置的粒度是长宽均0.5m的粒度,也就是一个水平位置对应的面积为0.5*0.5,那么久需要开辟一个1600*1600的二维数组,每个(x,y)处用半精度浮点数存高度时,则需要1600*1600*2byte的存储空间,即5m,会造成硬盘和内存的极大浪费。

为了减少对存储空间的占用,降低数据查询的复杂度。本方案中对水采用分块存储方式,将场景地图划分为多个区域块,通过二维数据存储数组(即上述第三数组)和一个指针数组实现对场景中水域信息的存储。具体的,每个存在水的区域块对应一个第三数组,每个第三数组存储对应区域块中的每个水平位置处的水的高度,如果水平位置处不存在水,则水的高度可以存储为0;指针数组中的每个元素为一个指针,一个指针对应一个区域块,如果一个区域块是不存在水的区域块,指针数组中对应的指针元素为设定值(如null),如果区域块是存在水的区域块,则指针元素为区域块对应的第三数组的存储位置即存储地址。采用该方案,水所对应的数据所占用的存储空间大大减小。

其中,地图块的标识可以根据实际需求设置。在一可选方案中,地图块的标识可以采用基于地图块在场景中的位置和场景中水平位置的粒度(即水平位置的长度的粒度和宽度的粒度)确定的标识。

仍以上述800m*800m的游戏场景为例进行说明。假设每个水平位置的粒度是长宽均0.5m的粒度,则该游戏场景中包括1600*1600个水平位置,若每个区域块的大小为100个*100个,该处的100个是指100个水平位置,即对应的实际大小为50m*50m,因此,800*800的游戏地图被划分为了16*16个区域块,因此,需要开辟一个16*16的二维指针数组。如图10中所示,图中每个小方块对应一个区域块,每个区域块中包含100*100个水平位置,因此,第三数组中的元素个数为100*100个,每个元素的值为对应位置的水的高度。如果一个区域块对应的区域有水,则指针数组中该区域块对应的指针指向该区域块对应的第三数组的存储地址,如果一个区域块对应的区域没有水,则对应的指针为空(即设定值为空)。

本示例中,地图块的标识通过每个地图块在场景地图中的位置以及水平位置的粒度确定,例如,对于图10所示的地图块a,该地图块为水平方向的横坐标方向上的第1个地图块且为纵坐标方向上的第1个地图块,则可以以(1,1)作为该地图块的标识,地图块a对应的实际区域范围为50m*50m,同样,对于地图块b,则为横坐标方向上的第3个地图块、纵坐标方向上第11个地图块,则可以以(3,11)来标识该地图块,而地图块c的标识则可以为(16,16)。若以a[i,j]来表示指针数组,则i和j的取值范围均为1至16,a[1,1]处的指针元素则为设定值或者为地图块a所对应的第三数组的存储位置。

对于上述800m*800m的场景,如果需要查找坐标为(172m,567m)处的水的高度,因为长宽均为0.5m的粒度,所以需要查找(344,1134)位置处是否存在水,则首先检查二维指针数组在(3,11)处的指针是否为空(该示例空即为设定值),如果为空,则无水;如果不为空,则代表有水,继续在二维指针数组在(3,11)处的指针指向的100*100二维数组里查找(44,34)处的高度,查找时间复杂度o(1)。

本公开的可选实施例中,该方法还可以包括:

设置每个体素的第二标记,每个体素的所述第二标记用于标识八方向中每个方向上该体素的相邻体素是否可行走。

在玩游戏的过程中,需要为游戏玩家即角色进行寻路,即玩家从当前所在的体素可以行走到哪个体素上。例如,假设水平位置(x,y)处有两个体素,第一个体素上下表面高度分别为4、0,第二个体素上下高度分别为10、7,水平位置(x,y+1)处有三个体素,上下表面高度分别为1、0;6、5;10、9,假设玩家当前站在(x,y)处第二个体素上,即玩家所在高度为10m,玩家在往(x,y+1)方向走,需要确定玩家可以走到(x,y+1)处的哪个体素上。

在一种可选方式中,可以采用遍历(x,y+1)处三个体素的方式,找到可以行走到的体素,在上述示例,玩家可到(x,y+1)处的第三个体素上,因为该体素上表面高度也为10m。然而在场景建筑复杂的情况下,这种遍历(x,y+1)所有体素的方式消耗还是有点大,对于客户端而言,客户端只有自己需要用体素行走,第三方都是通过转发过来的路点,因此,客户端效率影响不大,但是后台即服务器需要对所有玩家校验,遍历的方式消耗太大,因此需要优化。

在实际应用中,一般玩家当前所在的水平位置与该位置的邻居位置的地形相差不大,因此,玩家是有可能走到其邻居水平位置的任何一个体素上的,对于上述示例,如果玩家当前处于(x,y)处的第2个体素上,那玩家走到(x,y+1)处时,也很可能走到(x,y+1)处的第1个体素上、第2个体素上,或者第3个体素上。对于该问题,本发明实施例中,通过为每个体素上再加一个第二标记来标识玩家从当前体素能够走到邻居位置处的哪个体素上。具体的,可以为每个方向配置一个short类型的变量(该变量作为第二标记),每个方向上的该变量存储每个方向能走到哪个体素上,每个方向占用两个bit。对于上述示例,例如当前体素为(x,y)的第k个体素,short类型的变量的前两个bit为0代表可以走到(x,y+1)的第k个体素,为01代表可以走到(x,y+1)的第k+1个体素,为10代表可以走到(x,y+1)的第k-1体素,为11代表(x,y+1)的k-1、k、k+1三个体素都不可走,在玩家需要由(x,y)处行走到(x,y+1)处时,需要遍历(x,y+1)处所有体素。经统计发现两个bit为11的情况不到5%,因此极少的情况需要遍历邻居的所有体素,通过这种方式可以在近似o(1)的时间走到一个体素上,效率提升近10倍,但通过为体素设置第二标记的方式,会使得场景中的体素所占用的存储空间有所增加,例如对于秦时明月项目而言,每个场景的平均体素大小由6.9m增加到9.1m。

本发明实施例所提供的方案,通过体素合并、地面不存下表面高度、水不生成体素、控制体素生成范围、存储自管理(体素信息的存储方式)等方式优化,能够大大减少体素信息所占用的存储空间。

基于上述本发明实施例的方法,完成游戏中体素的生成以及其它游戏资源的生成及配置后,通过资源打包生成游戏的安装包,在通过压缩之后即可得到客户端的游戏包。游戏玩家在通过在线下载或其他方式获取到游戏包之后,在客户端的终端设备上通过游戏包加压缩后将各种游戏资源数据存储到终端设备的外存上,完成游戏的安装。在游戏运行时,将玩家角色当前所在游戏场景对应的游戏数据由外存加载到内存中,通过渲染等步骤完成游戏场景的绘制并显示到客户端。

基于本发明实施例所提供的方案,对于平均大小为800米*800米的18个游戏场景进行优化处理,优化后的18个场景,体素总大小124m,压缩后35m,压缩前最大场景占用15m,最小场景占用1m,平均占用6.9m,客户端在每个场景只需加载当前场景体素,所以客户端由于体素带来的内存增加最大为15m,客户端的游戏包大小增加35m,后台即服务器由于需要加载所有场景体素,所以后台由于体素内存增加,124m。在效率上,基于本发明提供的体素信息存储方式。在查找某个位置的所有体素时,时间复杂度为o(1),再通过预先计算每个体素可到邻居的哪个体素,从当前体素移动到邻居体素,时间复杂度近似于o(1)。因此,采用本发明实施例所提供的方案生成游戏时,有效解决了基于体素开发游戏时由于存储空间(主要是内存)占用过大导致很多项项目实现困难的问题。

基于图2中所示的方法,本发明实施例还提供了一种游戏数据的处理方法,如图11所示,该方法主要可以包括:

步骤s210:获取待加载游戏场景中的场景资源数据,场景资源数据包括待加载游戏场景中所有体素的体素信息;

步骤s220:在内存中创建一维的第四数组和一维的第五数组;

步骤s230:将待加载游戏场景中的每个水平位置处的所有体素信息加载到第四数组中,将每个水平位置处的体素信息在第四数组中的位置加载到第五数组中。

本方案中的方法适用于游戏运行过程中。

mmorpg游戏分为客户端和服务器两部分,在游戏运行过程中,玩家从客户端通过互联网登录服务器后才能进行游戏。在游戏过程中,玩家所扮演的角色与其它玩家所扮演的角色在虚拟世界的空间中进行实时互动。客户端在获取到游戏安装包后,将安装包解压缩进行游戏安装,各种场景资源数据即游戏资源被保存到外存(一般为硬盘)中。玩家登陆游戏时,客户端从硬盘中将客户端角色所在的游戏场景以及其他各种所需的数据读取到内存中,进而通过显示器呈现给玩家。用户在通过客户端登录游戏时,客户端与服务器通信以获取玩家的角色信息。

场景资源数据包括游戏场景中的场景对象的组成元素,对于本发明而言,游戏场景中的游戏对象是体素表示,因此,场景资源数据包括待加载游戏场景中所有体素的体素信息,具体包括待加载场景中每个水平位置处的所有体素的上表面高度和下表面高度,对于每个水平位置处的第一个体素,下表面高度默认为地面高度,如高度为零。

对于本发明实施例提供的该方法,可以适用于客户端,也可以适用于服务器段。可以理解的是,若该方法的执行主体为客户端,待加载游戏场景为当前游戏场景,若该方法的执行主体服务器,待加载游戏场景则为游戏所有的游戏场景。对于客户端而言,当前游戏场景是根据客户端角色(当前客户端所对应的玩家在游戏中所扮演的角色)在游戏中的当前位置确定的。

本发明实施例的该方案,通过两个数组实现体素信息在内存中的存储,一个数组存储所有体素信息,另一个数组存储每个水平位置处的体素信息在一个数组中的存储位置。由前文的描述可知,采用该存储方式,在将体素信息加载到内存中时,能够有效减少体素信息对内存空间的占用,且基于该方案在查找每个水平位置的体素信息时,可以首先在存储体素的位置的数组中查找相应水平位置的体素的位置,再基于查找到的位置在存储体素信息的数组中的相应位置查找到体素信息,基于本发明实施例的该方案,可以大大降低体素信息的查找时间复杂度。

由前文的描述可知,作为一可选方案,可以只将每个水平位置处的体素信息在第四数组中的起始位置加载到第五数组中,以进一步减少内存空间的占用。此时,在查找某一水平位置的体素信息时,可以基于该水平位置的起始位置和下一个水平位置的起始位置,得到该水平位置处的体素的个数,再进一步根据起始位置和体素个数即可在存储体素信息的数组读取到该水平位置处的所有体素的体素信息,大大降低了体素信息的查找时间复杂度。

具体的,对于基于本发明对应待加载游戏场景,根据待加载游戏场景中的每个水平位置,从电子设备的外存中用于存储体素信息的文件中读取每个水平位置的体素信息,将读取的体素信息存储到第四数组中,并将每个水平位置的体素信息在第四数组中的位置写入到第五数组中。其中,步骤s230中,在将体素信息和位置加载到相应的数组中时,具体可以是根据一定的存储顺序进行加载的,该顺序为游戏安装包生成时所配置好的存储顺序,是水平位置之间的相对顺序,如前文中所描述的按照(x,y)、(x,y+1)、……、(x,y+n)、(x+1,y)、(x+1,y+1)、……的顺序,依次将对应位置处的体素信息加载到第四数组中。

本发明的可选实施例中,若待加载游戏场景中存在水域,场景资源数据还包括存在水的地图块中的每个水平位置处的水的高度,该方法还包括:

根据存在水的地图块的个数,创建相应个数的二维的第六数组;

将每个地图块中的每个水平位置处的水的高度加载到对应的第六数组中;

创建二维的第二指针数组,指针数组的元素个数为游戏地图被划分成的所有地图块的个数,每个指针元素对应一个地图块,对于不存在水的地图块,第二指针数组中对应的指针元素为设定值,对于存在水的地图块,第二指针数组中对应的指针元素为地图块对应的第六数组的存储位置。

对应于图2中所示的方法的可选实施例中所提供的水域数据的存储方式,在待加载游戏场景中存在水时,则需要将水域所对应的场景资源数据即水的高度信息加载到内存中。由于水的存储方式是采用分块存储块的方案,因此,在将水对应的场景资源信息加载到内存中时,需要根据所有地图块的个数创建指针数组,数组中的一个指针元素对应一个地图块,如果地图块中包含水域,则指针元素的值为地图块对应的第六数组的存储地址,如果地图块中不包含水域,指针元素的值为设定值即可。采用该存储方式,可以进一步减少场景资源数据所占用的内存空间,并可以提高水数据的查找效率。具体的,在需要查找某一位置的水的高度时,则可以首先基于该位置所在的地图块对应的指针元素确定该区域块中是否存在水,如果对应的指针元素为设定值,则说明该位置处不存在水,否则,对应的指针元素则为该位置所在的地图块所对应的第六数组的存储地址,则根据指针元素所指向的地址查找到第六数组,从该数值的元素中查找到的该位置对应的元素的值,即为该位置处的水的高度。

本发明的可选实施例中,若方法的执行主体为客户端,待加载游戏场景为客户端对应的玩家角色当前所在的游戏场景,该方法还包括:

根据所加载的体素信息的上表面网格mesh生成第一navmesh;

基于预配置的第一扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第一navmesh行走到的体素确定为第一地面体素,第一地面体素的高度作为待加载游戏场景的地面高度;

确定每个第一地面体素的上表面mesh的优先级,并设置每个第一地面体素的上表面mesh的优先级标记,其中,若第一地面体素所在的水平位置的可行走区域的半径大于设定值,则第一地面体素的上表面mesh为第一优先级,否则为第二优先级,第一优先级高于第二优先级;

根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,其中,存在第二navmesh的区域为待加载游戏场景中的可行走区域。

navmesh即导航网格是3d游戏世界中用于实现动态物体自动寻路的一种技术,将游戏中复杂的结构组织关系简化为带有一定信息的网格,在这些网格的基础上通过一系列的计算来实现自动寻路。navmesh是由mesh经过体素化、地区生成、轮廓生成、多边形网格生成、高度细节生成等步骤生成,然后在导航网格上通过a*或d*等算法生成联通多边形列表,并从列表中找出最优路径。

本发明的可选实施例中,客户端寻路可以采用navmesh,后台即服务器端寻路可以采用jumppointsearch(跳转点),这是因为客户端只有一个玩家寻路,性能没有压力,但是玩家的路径必须好,不能贴边走,分级navmesh(即带优先级的navmesh)可以将路中间标记为高优先级,将路边缘标记为低优先级,这样寻出来的路径可以避免贴边问题。而后台npc(non-playercharacter,非玩家角色)的寻路重在快,后台需要对大量npc进行寻路,所以寻路必须快,jumppointsearch寻路速度是navmesh几十倍,满足性能要求,虽然jumppointsearch路径存在贴边问题,但是npc绝大多数都种在开阔地带,所以npc的路径很少有贴边的情况,因此后台可以采用jumppointsearch。

对于客户端而言,将生成的体素提取上表面mesh,提供给游戏引擎(如unity)并生成navmesh。为了生成精细的navmesh,在实际应用中,navmesh生成的体素精度可以高度体素的精度。例如,navmesh生成的体素精度可以为0.15米*0.15米*0.1米,而碰撞为了内存及效率考虑,采用的体素精度为0.5米*0.5米*0.1米。

此外,虽然整个场景体素化,但仍然需要地面高度,例如策划为了配置位置方便,npc出生位置(对于服务器而言),只配置水平坐标,没有配置高度时,高度默认为地面高度。一种获取地面高度的方式是取地面navmesh高度,但navmesh的高度不精准,比如在栏杆边缘附近,如图12中所示的游戏场景中,a所示的区域(颜色相对较深一些的区域)和b所示的区域(颜色相对较浅一些的区域)为不同优先级的navmesh,图中箭头所指的即为navmesh在该位置的高度,但并不是玩家站的地面高度。另外,需要注意的是,体素第一层虽然大部分情况都是地面,但也有例外,如图13所示的场景中,箭头1指向的才是地板,但第一层体素是箭头3所在的位置,所以不能直接拿第一层体素的上表面高度当作地面高度。

对于该问题,本发明实施例提供的方案为:首先将生成的体素提取上表面mesh,提供给unity并生成navmesh,给定一个扩散点,在体素上进行扩散,所有能通过navmesh行走走到的体素都加上标记,然后删掉无法行走到的体素,剩下的体素即为地面的体素,这些体素的高度即为地面高度。

前台即客户端在给玩家寻路时,需要寻出来的路径不能贴边,玩家尽量沿着路中间走,但navmesh寻出来的路径是贴边的,为了解决该问题,本发明通过对navmesh分优先级来实现,具体的,路边的navmesh优先级低,边的耗费代价高,路中间的navmesh优先级高,边的耗费代价低,因此寻出来的路径会优先考虑路中间的navmesh。如图14所示的场景中,玩家角色所站的颜色相对较深的navmesh为高优先级navmesh,颜色相对较浅的路边的navmesh为低优先级navmesh。3d游戏引擎(如unity)支持对navmesh分优先级,只需要提供的mesh标记优先级即可,因此,可以通过设置体素的上表面mesh的优先级,即可生成带优先级的navmesh。

在一种可选方式中,可以通过meijster算法计算体素所在的水平位置的可行走区域的半径。具体的,首先根据阻挡图,通过meijster算法计算sdf(signeddistancefield,有向距离场),sdf表示当前位置多大的半径内没有阻挡即可行走区域的半径,如果(x,y)处sdf为5,则表示(x,y)处5m内无阻挡。对于获取的地面体素,遍历地面体素,如果当前位置的sdf小于某个阈值,则该位置体素的上表面mesh标记为低优先级,否则该位置体素的上表面mesh标记为高优先级,然后将地面体素标记了优先级的mesh提供给unity生成优先级navmesh。

本发明的可选实施例中,若该方法的执行主体为服务器,待加载游戏场景为所有游戏场景,该方法还包括:

根据所加载的体素信息的上表面网格mesh生成第三navmesh;

基于预配置的第二扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第二navmesh行走到的体素确定为第二地面体素,第二地面体素的高度作为待加载游戏场景的地面高度;

基于第二地面体素的上表面网格mesh生成第四navmesh;

将存在第四navmesh的区域作为可行走区域,不存在第四navmesh的区域作为不可行走区域,生成阻挡图,阻挡图用于标识哪些场景中哪些区域可行走。

对于后台而言,后台需要阻挡图标记哪些区域可行走,从而对客户端的位置进行校验,而后台的寻路算法jumppointsearch也在阻挡图上进行,因此需要对后台生成阻挡图。客户端有navmesh的地方是可行走的区域,为了和客户端保持一致,后台可以根据客户端的navmesh生成阻挡图,但由于客户端的navmesh有多层,而后台的阻挡图只有地面一层,因此生成阻挡图时,客户端非地面的navmesh需要过滤。

与客户端确定地面体素的方式相同可以首先将生成的体素提取上表面mesh,提供给unity并生成navmesh,给定一个扩散点,在体素上进行扩散,所有能通过navmesh行走走到的体素都加上标记,然后删掉无法行走到的体素,剩下的体素即为地面的体素,再用地面体素上表面的mesh重新生成navmesh,重新生成的navmesh即为可行走区,没有navmesh的地方即为不可行走区。后台基于确定的可行走区和不可行走区,生成阻挡图即可。

本发明的可选实施例中,上述根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,具体可以包括:

生成待加载游戏场景的多边形mesh,其中,多边形mesh的高度小于体素的上表面mesh;

根据带优先级标记的第一地面体素的上表面mesh以及多边形mesh,生成带优先级标记的第二navmesh。

在游戏中,玩家角色在贴着墙边走时,容易与墙边发生碰撞,但是碰撞时不能卡住,需要角色沿着墙边的切线方向平滑移动。如图15中所示,灰色区域表示墙,玩家从a走到c时,c在墙内,但不能卡住,此时玩家需要在和墙的交点处d改变方向,沿墙切线方向移动到b。获取切线一般通过mesh计算,但本发明的方案中,碰撞均用体素实现,不需要mesh,又因为mesh占用空间大,因此,本发明实施例中,可以采用navmesh而非mesh计算切线。

由体素的上表面mesh生成的navmesh如图16中所示,生成的navmesh仍然有很多锯齿,因为体素的上表面mesh本身就有锯齿。如果根据含有大量锯齿的navmesh,计算切线对玩家的移动做平滑,效果并不好。但由前文描述可知,计算优先级navmesh,必须根据体素的mesh生成navmesh,因此可以在体素的mesh下面再垫一层原场景的mesh即采用现有方式生成的mesh。原场景mesh的优先级可以都标记为低优先级,因为原场景mesh高度比体素mesh高度低,因此有体素mesh的地方不会根据原场景mesh生成navmesh,只有在边缘地带,没有体素的mesh,才会根据原场景mesh生成navmesh。对于图16中所示的场景,最终生成的navmesh如图17中所示,图中s1区域和s2区域的navmesh仍然是由体素mesh生成,而s3所示的区域的navmesh由原场景mesh生成,并且s3区域的navmesh是平滑的,可以根据其切线对玩家移动做平滑。在实际应用中,为了加速计算,还可以对边缘区域在体素上做标记,只有在边缘区域才对玩家做平滑。

本发明的可选实施例中,该方法还可以包括:

接收到玩家角色的移动请求时,根据玩家角色的当前位置、移动方向和预配置的时间间隔,确定玩家角色的目标位置,移动请求为行走请求或飞行请求;

根据移动路径上的体素信息,基于预配置的碰撞检测条件,对玩家角色的目标位置进行碰撞检测,其中,移动路径是基于第二navmesh确定的由玩家角色的当前位置到玩家角色的目标位置之间的路径;

根据碰撞检测结果确定玩家角色的最终位置,根据玩家角色的最终位置控制玩家的移动。

碰撞检测即检测两个物体的物理体积是否有交集,对于本发明而言,碰撞检测是基于体素实现的,对游戏玩家的目标位置进行碰撞检测,即是在玩家角色由当前位置行走到目标位置时,移动路径上是否存在体素阻挡。基于体素进行碰撞检测的方式,与现有的基于bvh((boundingvolumehierarchy,bvh))的碰撞检测方式相比,效率能够明显提高。其中,碰撞检测条件是根据实际需要配置的,如在行走时,主要需要考虑以下几个因素:

相邻体素的高度差是否在合理范围内;从高处可以往低处走时,相邻体素的高度差是否大于向下走的最低高度;从低处往高处走时,相邻体素的高度差是否大于往上走的最高高度。

同样的,对于飞行功能而言,碰撞检测也是检测玩家角色的移动路径前方是否有体素阻挡。

在游戏中,为了实现玩家的行走以及轻功即飞行等功能,需要对进行碰撞检测,以确定玩家从当前位置到目标位置的路径上是否存在阻挡,即判断玩家是否能够到达目标位置,如果路径上存在阻挡,则需要根据碰撞检测的结果确定玩家的实际最终位置,从而控制玩家角色的最终位置控制玩家的移动。下面对玩家的行走和轻功两种功能分别进行说明。

一、行走

本发明的方案中,行走均在体素上进行,在每个心跳里,根据移动方向(由客户端玩家的操作确定的)和时间间隔,算出水平位移,根据当前位置和水平位移,算出新位置即目标位置,并对新位置进行碰撞检测。通常,行走的碰撞有以下几种情况:

一,邻居(邻居体素)太高,超过向上走的最高高度,例如,玩家角色往上走的最高高度为0.9m,如果当前体素的上表面高度与邻居体素的上表面高度大于0.9,则不可行走,发生碰撞;二,邻居太低,超过向下走的最低高度(如0.8m);三,走到邻居会碰头(体素高度差小于设定高度);四,邻居某个体素的上表面高度在当前高度向下走的最低高度和向上走的最高高度之间。

对于第一种情况下,则不可走,即玩家角色不能走到目标位置上,玩家角色不能走到发生碰撞时的邻居体素时,玩家角色的最终位置即为发生碰撞时的当前所在的体素;第二种情况下,如果玩家角色可以使用轻功,则以某个速度垂直下落,玩家角色的最终位置为垂直下落后所落到的体素上,如果不可以使用轻功,则此时不可行走;对于第三种情况,由前文描述可知,基于本发明实施例中提供的体素合并方案不会发生;第四种情况下可以直接走过去,即由当前体素的上表面行走到邻居体素的上表面。

对于第四种情况,在实际应用中,因为体素的特性,导致行走的区域并不平滑,如图18所示的房顶,生成的体素如图19所示,可以看出在房顶上行走会如走台阶一般,因此需要做平滑处理,从(x,y)的第二个体素走到(x,y+1)的第三个体素,在这两个体素之间行走,需要插值(x,y)的第二个体素和(x,y+1)的第三个体素的高度。

另外,在战斗副本场景中,不能使用轻功,因此不能掉到峡谷里,因为不能飞上来,例如在房顶、山顶或悬崖的边缘,玩家不能走到山下,但如果可以使用轻功,则以某个速度落下去,例如从房顶落到地面上。此时可以通过检查当前体素和想要走到的体素的高度差,假设人行走最多能走上的高度为0.9m,在不可使用轻功的场景,从(x,y)的第二个体素走到(x,y+1)的第三个体素时,如果第二个体素比第三个体素高,且高度差大于0.8m(0.8m略小于0.9m,保证走下去后可以走上来),在不可使用轻功的场景,则不可走下去,如果可以使用轻功,则可以以某个速度下落。

二、轻功

如果玩家有四段轻功,每一段轻功有自己对应的水平方向和垂直方向两条运动曲线,每段轻功在特定时间播放特定的动作。每个心跳里在两条运动曲线上采样,算出水平方向和垂直方向位移,根据位移算出玩家新位置,然后拿新位置进行碰撞检测。通常,轻功的碰撞有六种情况:

一,向上进体素,例如向上飞时头部撞上房顶;二,水平进体素,例如飞行中撞墙;三,向下进体素,例如落地;四,落水,水中无体素,通过水的高度判断;五,无碰撞;六,超出地图边界。

第一种情况,例如在玩家角色向上飞时,如果头部撞房顶,则需要以某个速度垂直下落,玩家角色的最终位置为垂直下落后所落在的体素的上表面;第二种情况,可以舍弃玩家水平位移,只取垂直位移,比如玩家当前位置是(1,2),高度是1.2m,玩家新位置是(1.2,2.2),高度是1.4m,则玩家位置仍然是(1,2),高度从1.2上升到1.4m,因为每个心跳移动距离很小,因此观察到的现象是玩家贴着墙面向上或向下飞行;第三种情况下,直接播放落地动画,轻功结束;第四种情况下,转入游泳状态;第五种情况下,玩家直接到新位置;第六种情况下,如果是前、后、左、右、上超出地图边界,需要以某个速度垂直下落,即沿着对应的地图边界垂直下落,如果是向下超出地图边界,需要拉回,拉回的位置可以是在轻功中以某个较长的时间间隔记录的垂直向下找到的可落脚位置,不需要记录太频繁,找落脚位置也有消耗。

需要说明的是,上述所列举的是行走或飞行中通常存在的几种情况。在实际应用中,可以根据实际需求配置不同的碰撞检测条件,以及检测到发生碰撞后,确定玩家角色的最终目的的方案。

本发明的可选实施例中,在玩家角色的最终位置不是玩家当前位置时,该方法还包括:

确定摄像机的目标位置;

检测摄像机的目标位置是否在体素内,或者,摄像机的当前位置和摄像机的目标位置之间是否存在体素阻挡;

若摄像机的目标位置在体素内,或者,摄像机的当前位置和摄像机的目标位置之间存在体素阻挡时,则将摄像机移动到射线与阻挡对应的体素的第一个交点的位置上,其中,射线的起点为玩家最终位置,射线的终点为摄像机的目标位置。

3d游戏中的摄像机即camera,是为玩家捕捉并展示世界的一种设备,用来控制游戏场景中的视角。也就是说,摄像机是为了拍摄玩家的可见区域,玩家角色移动时,摄像机也需要移动,因此,摄像机移动时也需要检测碰撞,检测到碰撞时需要移动到合适位置。

目前普遍做法是在玩家移动时,摄像机根据视线角度等计算位置,然后从玩家到摄像机打出一条射线,将摄像机放在射线和体素的第一个交点上,然而玩家和摄像机距离一般都在5m以上,每帧都在5m的距离以外检测射线和体素的交点比较耗时。

为了解决该问题,本发明实施例的该方案可以只在摄像机进入体素,以及摄像机旧位置和新位置之间有阻挡时,才将摄像机放在射线和体素的第一个交点上。检测摄像机是否在体素里很快,而摄像机是平滑移动,摄像机旧位置和新位置在一帧内很接近,所以检查摄像机旧位置和新位置之间是否有体素也很快,这一步的目的是防止玩家和摄像机一直在墙的两边,导致看不到玩家。

作为一种可选方案,可以采用bresenham算法计算射线和体素的交点。bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在n维光栅上最接近的点。这个算法只会用到较为快速的加法,常用于绘制电脑画面中的直线,是计算机图形学中最先发展出来的算法。

具体的,以startpos表示射线起点,endpos表示射线终点,collidepos为射线和体素交点。dir是射线单位向量,也表示射线走1米,x、y、z方向上分别走多少米,dir的倒数位为dirinfo,dirinfo表示x、y、z方向走1m,射线能走多少米。currvoxel表示startpos所在的三维长方体格子坐标,lefttoppos表示startpos所在的三维立方体格子六个顶点中最小的顶点,tmaxx、tmaxy、tmaxz表示遇到长方体格子的下一个x、y、z边,需要从射线起始位置走多远,m_splitxy、m_splitz表示xy(水平位置对应的方向)、z(高度方向)的体素粒度,本示例中,m_splitxy为0.5m,m_splitz为0.1m。如果tmaxx比tmaxy、tmaxz都小,表示沿着射线走,先碰到立方体的x边,此时currvoxel的x坐标加上stepx,如果tmaxx大于maxlength(射线的长度),表示startpos和endpos之间没有体素,直接返回,如果currvoxel在体素里,则表示startpos和endpos有阻挡,已知startpos、沿着射线走的距离tmax、方向向量dir,因此可以计算出碰撞位置collidepos,否则表示未到endpos且未遇到体素,因为此时已经到了长方体的x边,在x方向走了m_splitxy,在射线方向走了dirinfo.x*m_splitxy,因此目前沿着射线走的距离为tmaxx+dirinfo.x*m_splitxy。然后重新找出tmaxx、tmaxy、tmaxz中最小的,决定最先到长方体的x、y、z哪条边。重复上述方式,直至找到碰撞位置即交点或者确定不存在阻挡,如果存在阻挡,则把摄像机放在碰撞位置处的体素上。

如图20中所示,为基于bresenham算法确定交点的二维示意图,该示例中,startpos为(0.5,0),endpos为(4,2),需要找到startpos到endpos遇到的阻挡,即为黑色格子(3,2)。本示例中,dir为(0.8683,0.4962),dirinfo为(1.1517,2.0155),currvoxel为(0,0),lefttoppos为(0,0),stepx为1,stepy为1,m_splitx为1,m_splity为1,tmaxx为0.5758,tmaxy为2.0155。第一轮,tmaxx<tmaxy,currvoxel的x坐标加上stepx,为(1,0),未遇到阻挡,tmaxx为此时1.7275;第二轮,tmaxx<tmaxy,currvoxel的x坐标继续加上stepx,为(2,0),未遇到阻挡,tmaxx此时为2.8792;第三轮,tmaxx>tmaxy,currvoxel的y坐标加上stepy,为(2,1),遇到阻挡,直接返回阻挡位置:(0.5,0)+2.0155*(0.8683,0.4962),即(2.25,1)。

本发明的可选实施例中,若方法的执行主体为客户端,且配置了玩家实际活动区域边界,待加载游戏场景中的所有体素为待加载游戏场景中玩家实际活动区域边界所限定的区域内的体素。

对应于图2中所示的方法,本发明实施例还提供了一种游戏数据的处理装置,如图21所示,该处理装置100包括体素生成模块110和体素存储模块120。

体素生成模块110,用于生成游戏场景中的体素,游戏场景中的场景对象由至少一个体素构成,每个体素为一个长方体,每个体素的体素信息包括对应的长方体的上表面高度和下表面高度;

体素存储模块120,用于将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中;

其中,每个水平位置为游戏地图中水平面上的一块区域,每块区域的形状和大小为体素的上表面或下表面的形状和大小,垂直投影在同一水平位置上的体素为同一水平位置处的体素,每个水平位置处的第一个体素为上表面高度最小的体素。

可选的,体素存储模块可以具体用于:

按照预配置的水平位置之间的存储顺序,将每个水平位置处除第一个体素的下表面高度之外的体素信息存储到第一数组中,将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中。

可选的,体素存储模块在将每个水平位置处的体素信息在第一数组中的位置存储到一维的第二数组中时,可以具体用于

将每个水平位置处的体素信息在第一数组中的起始位置存储到一维的第二数组中。

可选的,若相邻的至少两个水平位置处的体素信息相同,体素存储模块再将每个水平位置处的体素信息存储到一维的第一数组中时,具体用于:

只将相邻的至少两个水平位置处中的一个水平位置处的体素信息存储到第一数组中,并在第一数组中设置与一个水平位置对应的第一标记,第一标记用于标识相邻的至少两个水平位置处的体素信息相同。

可选的,体素生成模块包括:

原体素生成单元,用于生成游戏场景中的原体素;

体素合并单元,用于将满足合并条件的原体素合并为一个体素,合并后的体素和未合并的原体素为游戏场景中的体素,合并条件包括:

位于同一水平位置处且高度差小于设定高度的相邻的原体素,和/或,封闭的场景对象的同一水平位置处的原体素;

其中,高度差是指相邻的原体素中高度较大的原体素的下表面与高度较小的原体素的上表面的高度差,合并后的体素的上表面高度为合并前高度较大的原体素的上表面高度,合并后的体素的下表面高度为合并前高度较小的原体素的下表面高度。

可选的,体素合并单元具体用于:

对于每一个水平位置处的原体素,若相邻的原体素之间的高度差不小于设定高度,则生成一个反体素;

其中,反体素的上表面为相邻的原体素中高度较大的原体素的下表面,反体素的下表面为相邻的原体素中高度较小的原体素的上表面;

确定所生成的所有反体素中的连通反体素;

其中,连通反体素是指与邻居反体素的交集高度差不小于设定高度的反体素,交集高度差是指两个反体素中高度较小的反体素的上表面高度与高度较大的反体素的下表面高度的差值,一个反体素的邻居反体素是指该反体素所在的水平位置的相邻水平位置处的反体素;

将所有连通反体素作为原体素,生成新的反体素,新的反体素为游戏场景中的体素。

可选的,若游戏场景中的场景对象下方悬空,该装置还包括:

第一指定体素生成模块,用于在场景对象下方距离场景最低可达高度第一设定距离的位置生成指定对象的体素,其中,指定对象的体素的体素信息不包括下表面高度,指定对象在游戏场景中不显示。

第三方面的可选实施方式中,该装置还包括:

实际活动边界配置模块,用于配置游戏场景中的玩家实际活动区域边界,其中,玩家实际活动区域的下边界位于游戏地图下边界以下第二设定距离处,第二设定距离不小于第一设定距离,游戏地图下边界的高度不大于场景最低可达高度;

第二指定体素生成模块,用于在游戏地图下边界下方的第一设定距离处生成指定对象的体素。

可选的,场景对象不包括水,若游戏场景中存在水,该装置还包括:

地图划分模块,用于将游戏地图划分为多个地图块,并设置每个地图块的标识;

水数据存储模块,用于根据存在水的地图块的个数,创建相应个数的二维的第三数组,每个第三数组用于存储对应的存在水的地图块中的每个水平位置处的水的高度;以及用于创建二维的第一指针数组,其中,第一指针数组的指针元素个数为所有地图块的个数,第一指针数组中的元素索引为地图块的标识,若地图块中不存在水,则对应的指针元素为设定值,若地图块中存在水,则对应的指针元素为地图块对应的第三数组的存储位置。

可选的,该装置还包括:

可行走标识设置模块,用于设置每个体素的第二标记,每个体素的第二标记用于标识八方向中每个方向上该体素的相邻体素是否可行走。

对应于图11中所示的方法,本发明提供了一种游戏数据的处理装置,如图22中所示,该处理装置200包括资源数据获取模块210和数据加载模块220。

资源数据获取模块210,用于获取待加载游戏场景中的场景资源数据,场景资源数据包括待加载游戏场景中所有体素的体素信息;

数据加载模块220,用于在内存中创建一维的第四数组和一维的第五数组,将待加载游戏场景中的每个水平位置处的所有体素信息加载到第四数组中,将每个水平位置处的体素信息在第四数组中的位置加载到第五数组中。

可选的,若待加载游戏场景中存在水域,场景资源数据还包括存在水的地图块中的每个水平位置处的水的高度,该装置还包括水资源数据加载模块,水资源数据加载模块用于:

根据存在水的地图块的个数,创建相应个数的二维的第六数组;

将每个地图块中的每个水平位置处的水的高度加载到对应的第六数组中;

创建二维的第二指针数组,指针数组的元素个数为游戏地图被划分成的所有地图块的个数,每个指针元素对应一个地图块,对于不存在水的地图块,第二指针数组中对应的指针元素为设定值,对于存在水的地图块,第二指针数组中对应的指针元素为地图块对应的第六数组的存储位置。

可选的,若该客户端为客户端装置,待加载游戏场景为客户端对应的玩家角色当前所在的游戏场景,该装置还包括导航网格生成模块,该模块用于:

根据所加载的体素信息的上表面网格mesh生成第一navmesh;

基于预配置的第一扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第一navmesh行走到的体素确定为第一地面体素,第一地面体素的高度作为待加载游戏场景的地面高度;

确定每个第一地面体素的上表面mesh的优先级,并设置每个第一地面体素的上表面mesh的优先级标记,其中,若第一地面体素所在的水平位置的可行走区域的半径大于设定值,则第一地面体素的上表面mesh为第一优先级,否则为第二优先级,第一优先级高于第二优先级;

根带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh,其中,存在第二navmesh的区域为待加载游戏场景中的可行走区域;

若该装置为服务器中的装置,待加载游戏场景为所有游戏场景,该装置还包括阻挡图生成模块,该模块用于:

根据所加载的体素信息的上表面网格mesh生成第三navmesh;

基于预配置的第二扩散点在待加载游戏场景中的体素上进行扩散,将能够通过第二navmesh行走到的体素确定为第二地面体素,第二地面体素的高度作为待加载游戏场景的地面高度;

基于第二地面体素的上表面网格mesh生成第四navmesh;

将存在第四navmesh的区域作为可行走区域,不存在第四navmesh的区域作为不可行走区域,生成阻挡图,阻挡图用于标识哪些场景中哪些区域可行走。

可选的,导航网格生成模块在根据带优先级标记的第一地面体素的上表面mesh,生成带优先级标记的第二navmesh时,具体用于:

生成待加载游戏场景的多边形mesh,其中,多边形mesh的高度小于体素的上表面mesh,多边形mesh的优先级低于体素的上表面mesh的优先级;

根据带优先级标记的第一地面体素的上表面mesh以及多边形mesh,生成带优先级标记的第二navmesh。

可选的,该装置还包括玩家位置控制模块,玩家位置控制模块用于:

接收到玩家角色的移动请求时,根据玩家角色的当前位置、移动请求所对应的移动方向和预配置的时间间隔,确定玩家角色的目标位置,移动请求为行走请求或飞行请求;

根据移动路径上的体素信息,基于预配置的碰撞检测条件,对玩家角色的目标位置进行碰撞检测,其中,移动路径是基于第二navmesh确定的由玩家角色的当前位置到玩家角色的目标位置之间的路径;

根据碰撞检测结果确定玩家角色的最终位置,根据玩家角色的最终位置控制玩家的移动。

可选的,在玩家角色的最终位置不是玩家当前位置时,该装置还包括摄像机位置确定模块,摄像机位置确定模块用于:

确定摄像机的目标位置;

检测摄像机的目标位置是否在体素内,或者,摄像机的当前位置和摄像机的目标位置之间是否存在体素阻挡;

若摄像机的目标位置在体素内,或者,摄像机的当前位置和摄像机的目标位置之间存在体素阻挡时,则将摄像机移动到射线与阻挡对应的体素的第一个交点的位置上,其中,射线的起点为玩家最终位置,射线的终点为摄像机的目标位置。

本发明实施例的装置可以应用于各电子设备中,例如,可以应用于移动终端设备中,也可以应用于固定终端设备中,还可以应用于服务器中,处理装置的功能实现可以具体由电子设备的处理器控制实现。

可以理解的是,本公开实施例中的装置的上述模块具有实现本发明相应实施例中所示的方法中相应步骤的功能,该功能可以通过硬件实现,也可以通过硬件执行相应的软件实现,该硬件或软件包括一个或多个与上述功能相对应的模块。上述各模块可以单独实现,也可以多个模块集成实现。对于数据的处理装置的具体功能描述可以参见前文中对方法中的对应描述,在此不再赘述。

由于本发明实施例所提供的装置为可以执行本发明实施例中的方法的装置,故而基于本发明实施例中所提供的方法,本领域所属技术人员能够了解本发明实施例的装置的具体实施方式以及其各种变化形式,所以在此对于该装置如何实现本发明实施例中的方法不再详细介绍。只要本领域所属技术人员实施本发明实施例中的数据的处理方法所采用的装置,都属于本发明所欲保护的范围。

基于与本发明实施例所提供的方法和装置相同的原理,本发明实施例还提供了一种电子设备,该电子设备可以包括处理器和存储器。其中,存储器中存储有可读指令,可读指令由处理器加载并执行时,可以实现本发明任一实施例中所示的方法。

本发明实施例还提供了一种计算机可读存储介质,该存储介质中存储有可读指令,可读指令由处理器加载并执行时,实现本发明任一实施例中所示的方法。

图23示出了本发明实施例适用的一种电子设备的结构示意图,如图23所示,该电子设备2000包括处理器2001和存储器2003。其中,处理器2001和存储器2003相连,如通过总线2002相连。可选的,电子设备2000还可以包括收发器2004。需要说明的是,实际应用中收发器2004不限于一个,该电子设备2000的结构并不构成对本发明实施例的限定。

其中,处理器2001应用于本发明实施例中,用于实现本发明实施例中数据处理模块的功能。收发器2004包括接收机和发射机,收发器2004应用于本发明实施例中,用于实现电子设备2000与其它设备之间的通信,实现数据的接收和发送。

处理器2001可以是cpu,通用处理器,dsp,asic,fpga或者其他可编程逻辑器件、晶体管逻辑器件、硬件部件或者其任意组合。其可以实现或执行结合本发明公开内容所描述的各种示例性的逻辑方框,模块和电路。处理器2001也可以是实现计算功能的组合,例如包含一个或多个微处理器组合,dsp和微处理器的组合等。

总线2002可包括一通路,在上述组件之间传送信息。总线2002可以是pci总线或eisa总线等。总线2002可以分为地址总线、数据总线、控制总线等。为便于表示,图23中仅用一条粗线表示,但并不表示仅有一根总线或一种类型的总线。

存储器2003可以是rom或可存储静态信息和指令的其他类型的静态存储设备,ram或者可存储信息和指令的其他类型的动态存储设备,也可以是eeprom、cd-rom或其他光盘存储、光碟存储(包括压缩光碟、激光碟、光碟、数字通用光碟、蓝光光碟等)、磁盘存储介质或者其他磁存储设备、或者能够用于携带或存储具有指令或数据结构形式的期望的程序代码并能够由计算机存取的任何其他介质,但不限于此。

可选的,存储器2003用于存储执行本发明方案的应用程序代码,并由处理器2001来控制执行。处理器2001用于执行存储器2003中存储的应用程序代码,以实现本发明实施例提供的装置的动作。

应该理解的是,虽然附图的流程图中的各个步骤按照箭头的指示依次显示,但是这些步骤并不是必然按照箭头指示的顺序依次执行。除非本文中有明确的说明,这些步骤的执行并没有严格的顺序限制,其可以以其他的顺序执行。而且,附图的流程图中的至少一部分步骤可以包括多个子步骤或者多个阶段,这些子步骤或者阶段并不必然是在同一时刻执行完成,而是可以在不同的时刻执行,其执行顺序也不必然是依次进行,而是可以与其他步骤或者其他步骤的子步骤或者阶段的至少一部分轮流或者交替地执行。

以上所述仅是本发明的部分实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1