detour
简介
寻路和空间推理工具包
组件接口
detour.gs
函数原型 | 函数作用 |
---|---|
object load_navigation(string path) | 加载导航网格 |
NavMesh.gs
导航数据
NavMeshQuery.gs
查询对象
@note 内部通过读写锁保证并发安全性。
函数原型 | 函数作用 |
---|---|
bool is_walkable(Vec3 pos, map opt_args = nil) | 判断给定位置是否可行走 |
array find_straight_path(Vec3 spos, Vec3 epos, map opt_args = nil) | 获取起始位置到目标位置的路径 |
样例
void dump_result(Vec3 spos, Vec3 epos, map info, array path)
{
printf("(%6.2f, %6.2f, %6.2f) -> (%6.2f, %6.2f, %6.2f):", spos.x, spos.y, spos.z, epos.x, epos.y, epos.z);
if (info == nil || path == nil)
{
printf(" failed due to either spos or epos is invalid.\n");
}
else
{
if (info.out_of_nodes)
printf(" [out of nodes]");
if (info.buffer_too_small)
printf(" [buffer too small]");
if (info.partial_result)
printf(" [partial result]");
printf(" %d vertices\n", path.length());
for (int i = 0; i < path.length(); ++i)
{
printf(" [%2d] (%6.2f, %6.2f, %6.2f)\n", i, path[i].x, path[i].y, path[i].z);
}
}
}
void naive_sample()
{
// 加载导航数据
object nav = detour.load_navigation("/maps/scene_data.bin");
defer nav.close();
printf("Naive navmesh: %O\n", nav.navmesh_info());
// 创建查询对象(通常,可以为每个玩家绑定一个查询对象,该对象不是线程安全的,不能同时被多个线程访问)
NavMeshQuery query = nav.create_query();
defer query.close();
map info = nil;
array path = nil;
Vec3 spos = Vec3(647.595703, 0.00000000, 432.997498);
Vec3 epos = Vec3(520.134644, 0.00000000, 700.356812);
// 寻路,返回路径和相关信息
let info, path = query.find_straight_path(spos, epos);
dump_result(spos, epos, info, path);
spos = Vec3(523.156128, 0.00000000, 521.997314);
epos = Vec3(520.134644, 0.00000000, 700.356812);
// 寻路(由于存在阻挡,两个点不可达)
let info, path = query.find_straight_path(spos, epos);
dump_result(spos, epos, info, path);
// 寻路,通过walkable_bits忽略特定的阻挡类型,这意味着可以通过相应的地块
let info, path = query.find_straight_path(spos, epos, {
"walkable_bits": 0x0001
});
dump_result(spos, epos, info, path);
}
void obstacle_sample()
{
// 加载导航数据,该网格支持动态障碍物(导航对象内部通过读写锁确保并发安全性)
object nav = detour.load_navigation("/maps/scene_data.obstacle.bin");
defer nav.close();
printf("Obstacle navmesh: %O\n", nav.navmesh_info());
// 创建查询对象(通常,可以为每个玩家绑定一个查询对象,该对象不是线程安全的,不能同时被多个线程访问)
NavMeshQuery query = nav.create_query();
defer query.close();
map info = nil;
array path = nil;
Vec3 spos = Vec3(694.590820, 0.00000000, 577.246033);
Vec3 epos = Vec3(574.161011, 0.00000000, 708.750977);
// 在原始网格上寻路
let info, path = query.find_straight_path(spos, epos);
dump_result(spos, epos, info, path);
// 在路径上添加障碍物
int obstacle_id = nav.add_cylinder_obstacle(Vec3(575.5, -0.5, 705.1), 1.0, 2.0);
// 调用update提交障碍物更新操作(可以创建一个协程来提交修改)
while (!nav.update(0.0))
;
// 添加障碍物后再次寻路,可以看到路径变化
let info, path = query.find_straight_path(spos, epos);
dump_result(spos, epos, info, path);
// 移除障碍物(这里force_update设置为true以立即提交修改)
nav.remove_obstacle(obstacle_id, true);
// 再次寻路,与原始网格寻路结果相同
let info, path = query.find_straight_path(spos, epos);
dump_result(spos, epos, info, path);
}
void main()
{
naive_sample();
obstacle_sample();
}