​01

效果演示

Cocos Creator 版本:3.4.1

该 demo 演示了增加/删除角色、增加/删除障碍物、多角色寻路、动态规避障碍物、上/下坡度、显示/关闭导航网格及实时路径

02

导航网格简介

RecastNavigation:

https://github.com/recastnavigation/recastnavigation

谷歌开源的一款非常强大的寻路系统,被广泛的应用于各大游戏引擎中

demo 中的素材是取自该系统

Babylon.js:

https://doc.babylonjs.com/extensions/crowdNavigation

微软开源的基于 web 的 3D 游戏引擎

recast.js 也是取自该引擎

个人理解:

根据一系列 mesh 中的顶点信息,实时计算可达路径

03

准备工作

1拷贝相关代码

将 Babylon.js 源码中 recast.js 相关的代码拷贝到自己的项目中

把 INavigationEngine.ts 和 recastJSPlugin.ts 看一遍,便可以基本了解他们的使用方法

2导入 recast.js

这里将 recast.js 以插件脚本的形式导入

关于插件脚本的官方文档:
https://docs.cocos.com/creator/manual/zh/scripting/external-scripts.html

04

实现方法

Babylon.js 中有详细的使用介绍以及参数说明:

https://doc.babylonjs.com/extensions/crowdNavigation/createNavMesh

1初始化 recast.js

之前已经将 recast.js 以插件脚本的形式导入了,这里可以直接使用

let recastInjection = await new Recast();this.recastJSPlugin = new RecastJSPlugin(recastInjection);

2初始化 NavMesh

根据场景需求设定合适的导航网格参数,每个参数的意义在 d.ts 中都有详细的说明

let navmeshParameters: INavMeshParameters = {    cs: 0.2,    ch: 0.2,    walkableSlopeAngle: 35,    walkableHeight: 3,    walkableClimb: 2,    walkableRadius: 1,    maxEdgeLen: 12.0,    maxSimplificationError: 1.3,    minRegionArea: 8,    mergeRegionArea: 20,    maxVertsPerPoly: 6,    detailSampleDist: 6,    detailSampleMaxError: 1,    tileSize: 16,};this.recastJSPlugin.createNavMesh(meshRenderers, navmeshParameters);this.recastJSCrowd = this.recastJSPlugin.createCrowd(10, 1) as RecastJSCrowd;

这里需要对 recastJSPlugin.ts 中的 createNavMesh 做一下适配,根据 cocos 的 mesh 创建导航网格

其中 meshRenderers 的类型为 MeshRenderer[],我们收集需要的模型来构建导航网格

为了收集方便,我们可以将模型都集中到一个节点下,然后通过下面的代码来获取该节点下所有的 MeshRenderer 组件

node.getComponentsInChildren(MeshRenderer);

根据 MeshRenderer 组件可以获取该模型中 mesh 的顶点位置及索引数据

不过这里获得的顶点位置是相对坐标,我们需要转换成世界坐标

for (pt = 0; pt < info.positions.length; pt += 3) {    Vec3.fromArray(position, info.positions, pt);    Vec3.transformMat4(transformed, position, worldMatrix);    positions.push(transformed.x, transformed.y, transformed.z);}

最后将收集到的所有顶点位置和索引数据传递给 NavMesh,以此来构建导航网格

let { positions, offset, indices } = this.getMeshData(meshRenderers);this.navMesh.build(positions, offset, indices, indices.length, rc);

3角色

· 创建角色

根据角色形象设定合适的角色参数,同样可以在 d.ts 中找到参数的详细说明

addAgent 返回该角色的唯一 ID,后续的一系列操作都要基于该 ID

addAgent(position: Vec3, agentParams?: IAgentParameters) {    position = this.recastJSPlugin.getClosestPoint(position);    if (!agentParams) {        agentParams = {            radius: 0.5,            height: 1,            maxAcceleration: 20,            maxSpeed: 6,            collisionQueryRange: 2.5,            pathOptimizationRange: 0,            separationWeight: 1,        };    }    let agentIndex = this.recastJSCrowd.addAgent(position, agentParams);    return agentIndex;}

· 删除角色

根据角色 ID,删除该角色

this.recastJSCrowd.removeAgent(id);

4寻路

根据角色 ID,导航至目的地,如果目的地不可达,会自动导航至离目的地最近的位置

this.navMeshAgent.agentGoto(agentID, targetPosition);

也可以主动获取目的地最近的可达位置,然后导航至此

this.recastJSPlugin.getClosestPoint(position);

需要在 update 中驱动导航网格,才能实时获取到角色的最新状态

update(deltaTime: number) {    if (this.recastJSCrowd) {        this.recastJSCrowd.update(deltaTime);    }}

根据角色 ID,获取角色在导航网格中的坐标,设置其位置

node.setPosition(this.recastJSCrowd.getAgentPosition(id));

根据角色 ID,获取角色当前的速度向量,设置其朝向

为了避免发生一些鬼畜行为,这里对速度向量做一个过滤

let vel = this.navMeshAgent.getAgentVelocity(id);if (vel.length() > 0.2) {    node.forward = vel;}

5障碍物

· 创建障碍物

recast.js 提供了两种障碍物类型的动态创建

圆柱体:

let obstacle = this.recastJSPlugin.addCylinderObstacle(position, radius, height);

立方体:

let obstacle = this.recastJSPlugin.addBoxObstacle(position, extent, angle);

· 删除障碍物

根据创建障碍时返回的信息可以直接删除

this.recastJSPlugin.removeObstacle(obstacle);

6调试信息

· 导航网格

创建导航网格显示所需的节点及材质

initDebugNavMesh() {    this.debugMaterial = new Material();    this.debugMaterial.initialize({        effectName: "unlit",        defines: {            // USE_ALBEDO_MAP: true,        },        states: {            primitive: gfx.PrimitiveMode.LINE_STRIP,            rasterizerState: {                cullMode: gfx.CullMode.NONE,            }        },    });    this.debugMaterial.setProperty("mainColor", Color.RED);    this.nodeDebugNavMesh = new Node("DebugNavMesh");    let meshRenderer = this.nodeDebugNavMesh.addComponent(MeshRenderer);    meshRenderer.setMaterial(this.debugMaterial, 0);    this.nodeDebugNavMesh.parent = director.getScene();}

recast.js 中获取导航网格信息后,使用 utils.createMesh 创建 mesh,然后赋值给 meshRenderer

let mesh = utils.createMesh({ positions: positions, indices: indices, doubleSided: false, primitiveMode: gfx.PrimitiveMode.LINE_STRIP });meshRenderer.mesh = mesh;

· 路径

recast.js 可以根据起始点和目标点计算出当前路径,但该路径不是一成不变的

let pathPoints = this.recastJSPlugin.computePath(start, end);

然后使用 Line 组件将该路径画出来

let node = new Node();node.parent = agent;let linePath = node.addComponent(Line);linePath.worldSpace = true;linePath.width.constant = 0.2;linePath.color.color = Color.GREEN;linePath.positions = pathPoints;

完整 demo:

子曰:“不患人之不己知,患不知人也。”

【解读】

孔子教育学生,在处世上要有人不知而不愠的精神,能够在寂寞中做成应该做的事业,完成应该具有的仁德修养。学,是为了自己的进步,而不要把精力用于怨天尤人上。处世是需要了解别人的,自己心态平和,才能真实地了解别人。不去苛求别人,要把精力用于提升自己的能力上。君子不担心没有人了解自己,不忧虑不能树立美好的名声,只忧虑自身的修养不够深厚,不能去充分了解别人。

更多教程

请扫码关注

Cocos Creator | 导航网格自动寻路:多角色寻路、动态规避障碍物、上/下坡度等相关推荐

  1. 麒麟子Cocos Creator 3D研究笔记三:角色换装(无动画)

    零.效果展示 先来两张图 在线演示地址: https://showcase.ukylin.net/avatar/ 3D换装有两种情况,一种是身体各部件(如头发.上衣.裤子.手套.鞋子等身体各部分),另 ...

  2. 麒麟子Cocos Creator 3D研究笔记四:天空盒动态更换与IBL效果

    麒麟子Cocos Creator 3D研究笔记之材质IBL与天空盒动态切换 在线演示地址: https://showcase.ukylin.net/skybox/ 天空盒对于3D渲染场景来说,有着不个 ...

  3. 【Cocos Creator】 使用 TTF 以及文本配置动态生成位图字体的解决方案

    游戏开发,需要使用字体. 直接使用 TTF 字体,其优点是开发特别省事. 而缺点却是很要命: TTF 字体文件过大,包含了不必要的字,增大了包体,减缓了加载速度: 部分平台不支持 TTF 文件的加载: ...

  4. Cocos Creator 性能优化:DrawCall

    Cocos Creator 性能优化:DrawCall(全面!) title: Cocos Creator 性能优化:DrawCall 前言 在游戏开发中,DrawCall 作为一个非常重要的性能指标 ...

  5. Cocos Creator - 动态合图(dynamicAtlasManager)

    步骤 Cocos Creator - 动态合图(dynamicAtlasManager) 前言 启用.禁用动态合图 贴图限制 支持定制的渲染组件 调试 总结 Cocos Creator - 动态合图( ...

  6. 大神驾到 | 腾讯光子大牛的 Cocos Creator 网络通用框架(强势围观)

    编者按 作者,宝爷.宝爷是光子工作室的开发工程师,谦称自己为一枚码农,是一个热爱游戏.热爱开发.热爱学习并坚持沉淀知识的开发者,曾写过<精通 Cocos2d-x 游戏开发>基础卷与进阶卷, ...

  7. Cocos Creator3.x NavMesh导航网格寻路(一)

    前言 在游戏开发过程中,寻路可能是大多数游戏都必不可少的功能.2d游戏中最常用的就是A* 寻路了.在3d游戏中,对于一些简单的,没有高度地面A* 寻路同时也是可以使用的,但是对于一些地面比较复杂的游戏 ...

  8. Cocos Creator3.x NavMesh导航网格寻路

    前言 在游戏开发过程中,寻路可能是大多数游戏都必不可少的功能.2d游戏中最常用的就是A* 寻路了.在3d游戏中,对于一些简单的,没有高度地面A* 寻路同时也是可以使用的,但是对于一些地面比较复杂的游戏 ...

  9. Cocos Creator3.x:NavMesh 导航网格寻路(二)

    前言 继Cocos Creator 3.x :NavMesh寻路后,菜鸟继续对寻路功能进行完善和测试,对除了web平台之外的其他平台进行支持与测试,目的是使咱们的寻路动能可以支持更多的场景. 在线体验 ...

  10. [unity3d]recast navigation navmesh 导航网格 寻路算法 源码分析

    recast navigation navmesh导航网格算法源码分析 Author:  林绍川 recast navigation navmesh是unity3d ue4内置的寻路算法 本文为了方便 ...

最新文章

  1. 微信小程序 点击卡片切换 动画效果
  2. PHP 获取数组最后一个值
  3. Entity Framework 出现 此 ObjectContext 实例已释放,不可再用于需要连接的操作 的错误...
  4. 实现框架页面iframe的背景透明方法
  5. Luogu P2920 时间管理【二分答案】
  6. 091_类数组对象转为数组
  7. 数据结构和算法解:第九章 算法设计技巧
  8. 科技谋定功能性农业-农业大健康:中科微研携手从玉农业
  9. 汇编--两种过程定义的方式,调用方式。
  10. 蓝桥杯第五届省赛JAVA真题----七对数字
  11. android 应用切换滑动,Android应用中利用ViewPager实现多页面滑动切换效果示例
  12. python中对象的概念是什么_python面向对象编程的基本概念
  13. 使Fiddler4抓包微信小程序
  14. 在Outlook 2013中发送给多个收件人时如何隐藏电子邮件地址
  15. 曹则贤:从一元二次方程到规范场论 | 中国科学院2022跨年科学演讲
  16. CTex下载地址和方法
  17. 网站克隆工具_科研|值得收藏的分子生物学必用工具(第二弹~)
  18. 百度地图瓦片下载工具(仅供学习)
  19. 8位可控加减法电路设计
  20. java excel checkbox_在Java窗体表格中插入复选框

热门文章

  1. 计算机多媒体话筒声音怎么调,音频调节器怎么调试麦克风 音频调节器调试麦克风方法介绍...
  2. kali linux 源码免杀,shellcode超级免杀
  3. 进行单元测试时一直报这个错,原因是缺少aspectjweaver包
  4. 中彩分析家 v7.18 build 1203 怎么用
  5. 利用树莓派为HP LaserJet 1020配置无线打印功能
  6. 用WPS2000制作勾股定理教学课件(转)
  7. TimesTen In-Memory Database
  8. 软件工程工具图(软件开发过程中可能用到的工具图)
  9. 浅谈大比例尺数字地形图的缩编方法
  10. idea设置炫酷主题