在3D MMO或者其他类型的游戏中,通常需要进行寻路处理,地图针对寻路有多种方案,比如划分格子,凸多边形等,本篇介绍一种比较常用的navigation mesh的方式来进行寻路。不过整套navmesh的算法比较复杂,没有深入的研究写不出来,我们使用网上开源的解决方案,google的recast方案。我们使用的开发环境是win7 + vs2013.

  一、服务器端recast的安装和使用

  1、先从github上面下载recast的源代码

  2. 源代码下载下来之后,需要我们自己进行编译,recast使用预编译工具premake,需要premake.lua。先下载lua,然后单独下载premake5,否则premake5.lua不能使用。将下载好的premake.exe放到和premake5.lua的同一目录下,然后在控制台运行premake.exe vs2013(根据自己的IDE版本号),就会生成vs2013的解决方案sln文件。

  2. recast的测试程序中,用到了SDL的相关库,这个比较简单,下载一个SDL-devel的库就可以了,然后看下RecastDemo里面的配置目录,copy进去就可以编译通过了。中间编译的时候,可能由于vs2013版本,会提示min,max这些函数没有定义,只要#include对应的STL库头文件<algorithm>就可以了

  3. 成功编译了recast相关的库,Detour,Recast等,我们一开始对于如何使用recast可能一点概念都没有,不过recast已经考虑到了这一点,工程中有一个RecastDemo程序,是用来示例如何使用recast的。

  4. 使用recastDemo,我们可以根据场景的.obj文件,来生成navmesh,和导入我们自己生成的navmesh,不过这都是我们通过recast开源工具生成的。实际的游戏中,我们需要的是从客户端生成的navmesh,然后导入到服务器中进行解析。

  二、Unity3D客户端的navmesh生成

  unity3D是自带navmesh agent的,可以自己生成navmesh,并且导出navmesh,不过它的导出navmesh,我查下来是需要自己写代码的,而且navmesh agent是修改过导出navmesh文件格式的,也就是说我们recast C++代码是不能直接使用的。后来我又搜索了一下recast for Unity这个插件,这个插件是有源代码的,不过如果正常购买需要$50。

  对于这个插件当时研究了比较长的时间,一开始导出了一下它的navmesh格式,然后用C++recast导入试了一下,发现格式肯定是不一样的了。然后就仔细研究了一下两边生成navmesh时的格式差异,针对TileMesh存储的时候,两边是不一致的,本来想直接修改C#代码来达到两边一致,不过由于对C#的序列化不够熟悉,就放弃了。不过应该可以直接改成一致,这个后面有时间可以再深入研究一下。

  后来使用了KBEngine修改过的CritterAI,它导出来的navmesh文件,在KBEngine中是能直接使用的。然后把我们服务器中解析navmesh的格式,改成和KBEngine一致就可以了。代码还是非常简单的,代码如下:

    bool NavMeshLoader::load_cai(const char* path) {
FILE* fp = fopen(path, "rb");
if (!fp) return false; // Read header.
NavMeshSetHeader_CAI header;
size_t readLen = fread(&header, sizeof(NavMeshSetHeader_CAI), , fp);
if (readLen != )
{
fclose(fp);
return false;
} if (header.version != NAVMESHSET_VERSION)
{
fclose(fp);
return false;
} dtNavMesh* mesh = dtAllocNavMesh();
if (!mesh)
{
fclose(fp);
return false;
}
dtStatus status = mesh->init(&header.params);
if (dtStatusFailed(status))
{
fclose(fp);
return false;
} // Read tiles.
for (int i = ; i < header.tileCount; ++i)
{
NavMeshTileHeader tileHeader;
readLen = fread(&tileHeader, sizeof(tileHeader), , fp);
if (readLen != )
{
fclose(fp);
return false;
} if (!tileHeader.tileRef || !tileHeader.dataSize)
break; unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
if (!data) break;
memset(data, , tileHeader.dataSize);
readLen = fread(data, tileHeader.dataSize, , fp);
if (readLen != )
{
fclose(fp);
return false;
} mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, );
} fclose(fp);
m_navMesh = mesh;
m_navQuery = dtAllocNavMeshQuery(); status = m_navQuery->init(m_navMesh, );
if (dtStatusFailed(status))
{
return false;
} return true;
}

  KBEngine中和RecastDemo中解析navmesh主要就是NavMeshSetHeader头结构不一致,其他的都一样,所以还是比较简单的。

  能正常解析navmesh文件之后,就是对地图进行寻路了,在这里主要使用了RecastDemo中寻路的代码,进行了本地化的修改。

  

  三、 使用recast navigation遇到的问题

  1、其中有段时间,我对于客户端生成的navmesh,和服务器生成的navmesh在坐标系上不一致,感觉很困惑,甚至想要不要自己用3DMax之类的工具重新导入地图模型,然后修改坐标系,这现在看来很可笑,主要还是对于navmesh的生成原理不是很懂。其实客户端生成的navmesh是带有自身坐标系和相对坐标的。之前之所以有那种困惑,是因为服务器用的是recastDemo中生成的navmesh,客户端生成了自己的,根本就是两种世界,两种坐标,当然不一致了!!

  2、其实CritterAI的底层是C++写的dll,通过unity导入进工程,然后生成navmesh的,只要符合unity使用dll的规则,我们其实也可以使用recast的源码,然后改成unity能够使用的dll来导出navmesh。这个后面可以试试

服务器使用recast navigation的更多相关文章

  1. CritterAI与Recast Navigation寻路

    版权声明:本文为博主吴欣伟原创文章,未经博主允许不得转载. 前言 这篇文章写于去年,由于工作需要,故写出这个研究文档,发现网上有关此寻路库的中文资源十分稀少,故发布出来与诸位共享交流,如文中有不对之处 ...

  2. Unity NavMesh 格式 解析 分析 对比 Recast Navigation

    工具软件 Excel Nodepad++ Sublime Unity 5.4 / 5.6 VS RecastDemo CodeBlocks 分析过程以Unity项目-Demo13为例 一. 创建测试模 ...

  3. Recast & Detour & TerrainExport Study Feeling

    Recast Navigation和Terrain Export终于算是有点成果了.今天作一个简单的总结,顺便写一些话激励自己. 这个项目的成功对于我这个算法又烂,而又不懂3d图形学的人来说,感觉真是 ...

  4. recast 生成navmesh主要流程

    参考:      critterai  http://www.critterai.org      recast & Detour https://github.com/recastnavig ...

  5. php项目------浏览器导航开发

    最近项目不是很急,把以前做的php项目分享一些给大家,希望对各位有所帮助:很简单的一个项目,本人用来练习ThinPHP框架的. 浏览器导航开发,php+mysql+apache,ThinkPHP3.2 ...

  6. 第八章:BOM

    /* * bom: * 提供了浏览器接口; * w3c为了把javascript最基本的只是标准化已经将bom的主要方面纳入html5规范*/ console.log(window); !(funct ...

  7. 搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 (1)

    搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 原文地址(英文):http://www.networkcomms.net/creating ...

  8. Unity. Navigation和寻路

    Navigation Static:不会移动.可以用于计算可行走区域.例如:地板.墙.静态障碍物. 将一个物体选为Navigation Static:Navigation窗口-> 勾选项

  9. Unity3d导出Recast geomset.txt

    Unity3d导出Recast geomset.txt (金庆的专栏) Recast Demo 输入需要 geomset.txt 文件来指定区域类型. 以ObjExporter.cs为基础,编写Uni ...

随机推荐

  1. HDU--杭电--1026--Ignatius and the Princess I--广搜--直接暴力0MS,优先队列的一边站

    别人都是广搜+优先队列,我没空临时学,所以就直接自己暴力了 Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)     ...

  2. BaseHttpListActivity,几行代码搞定Android Http列表请求、加载和缓存

    Android开发中,向服务器请求一个列表并显示是非常常见的需求,但实现起来比较麻烦,代码繁杂. 随着应用的更新迭代,这种需求越来越多,我渐渐发现了实现这种需求的代码的共同点. 于是我将Activit ...

  3. Java String.split()小点

    java String.split(); 别的不说,单说其中一个问题,这个函数去切分空字符串时,得到的结果: public static void main(String[] args) {// St ...

  4. 转载《遭受arp攻击怎么办》

    ARP(Address Resolution Protocol,地址解析协议)协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的进行.ARP攻击仅能在以太网(局 域网如: ...

  5. 使用Mulesoft建立webservice, simple方式,POJO

    Mulesoft是使用CXF来支持web service,有三种方式 1.JAX-WS 2.Simple, POJO 3. Proxy, pass-throught 本文介绍POJO,最简单的方式 1 ...

  6. Scala编程--基本类型和操作

    如果你熟悉Java,你会很开心地发现Java基本类型和操作符在Scala里有同样的意思.然而即使你是一位资深Java开发者,这里也仍然有一些有趣的差别使得本章值得一读.因为本章提到的一些Scala的方 ...

  7. EXCEL里面的数字显示为文本 不用科学计数法显示

    1. 在输入这一串数字前加撇号“'”(英文状态下的单引号)即可.2. 先将这一列设置为“文本”格式,然后直接输入这一串数字即可.   已经输入好了数字,那估计你这些数字的后三位都已经全变成“0”了,用 ...

  8. 活用shape、selector和layer-list来打造自己想要的背景效果

    活用shape.selector和layer-list来打造自己想要的背景效果 2016-04-27 13:52 281人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转 ...

  9. 【zz】matlab 直方图匹配

    原文地址:http://www.cnblogs.com/tiandsp/archive/2012/12/19/2825418.html 直方图匹配或叫做直方图规定化都可以,是把原图像的直方图按照给定的 ...

  10. ACM 暴力搜索题 题目整理

    UVa 129 Krypton Factor 注意输出格式,比较坑爹. 每次要进行处理去掉容易的串,统计困难串的个数. #include<iostream> #include<vec ...