当前位置: 首页 > news >正文

[Unity]AstarPathfindingProject动态烘焙场景

需求

项目是MMO大场景,按地块划分了10x10的大格子。角色移动时动态更新周边场景,且角色还有传送功能。
项目中寻路用了AstarPathfindingProject的Grid。因此需要动态烘焙寻路信息。

核心代码

    private void bakeAStarPath(){AstarPath astarPath = AstarPath.active;if (astarPath == null){Debug.LogError("AstarPath 实例未找到,请确保场景中有 AstarPath 组件!");return;}// 获取第一个 GridGraph(假设你只有一个 GridGraph)GridGraph gridGraph = astarPath.data.gridGraph;if (gridGraph == null){Debug.LogError("GridGraph 未找到,请确保已添加 GridGraph!");return;}float newGraphCenterX = curCenterXIndex * xSize + xSize * 0.5f;float newGraphCenterZ = curCenterZIndex * zSize + zSize * 0.5f;gridGraph.center = new Vector3(newGraphCenterX, 0, newGraphCenterZ);gridGraph.width = (int)xSize * 3;gridGraph.depth = (int)zSize * 3;//// 重新计算并扫描 GridGraphastarPath.Scan();

可能遇到的问题

  • 1,烘焙后场景内可通行区域是不可通行的

一般是时机问题,烘焙的时候可能场景还没有准备好。笔者的做法是场景加载好后延迟一个物理帧再烘焙。因为烘焙的底层是通过射线来检测的,确保场景中的物理数据准备就绪再烘焙可以规避这个问题。

yield return new WaitForFixedUpdate();
//TODO:bake callback
  • 2,加了物理帧延迟后依旧很小概率会出现烘焙不上的问题

取一个必可通行的点(比如主角的脚下),检测该点所在的node是否可通行,若不可通行,再重复多次bake,直至可通行。

    int retryCount = 0;private void bakeAStarPath(){AstarPath astarPath = AstarPath.active;if (astarPath == null){Debug.LogError("AstarPath 实例未找到,请确保场景中有 AstarPath 组件!");return;}// 获取第一个 GridGraph(假设你只有一个 GridGraph)GridGraph gridGraph = astarPath.data.gridGraph;if (gridGraph == null){Debug.LogError("GridGraph 未找到,请确保已添加 GridGraph!");return;}float newGraphCenterX = curCenterXIndex * xSize + xSize * 0.5f;float newGraphCenterZ = curCenterZIndex * zSize + zSize * 0.5f;gridGraph.center = new Vector3(newGraphCenterX, 0, newGraphCenterZ);gridGraph.width = (int)xSize * 3;gridGraph.depth = (int)zSize * 3;//// 重新计算并扫描 GridGraphastarPath.Scan();var checkNode = gridGraph.GetNearest(new Vector3(selfRolePos.x, 0, selfRolePos.z));bool bakerFlag = false;if (checkNode.node.Walkable){ bakerFlag = true;}else{ bakerFlag = false;}if (bakerFlag == false){Debug.LogError("GridGraph扫描失败,准备重新扫描");if (retryCount < 3){//再次扫描TimerTween.Delay(0.5f, () =>{retryCount++;this.bakeAStarPath();}).SetTag("delayBakerA*" + retryCount).Start();}}else{Debug.LogError("GridGraph Center 已更新为: " + gridGraph.center + " 并完成重新扫描, xIndex:" + this.curCenterXIndex + ", zIndex:" + this.curCenterZIndex);retryCount = 0;} }
  • 3,异步烘焙

插件也提供异步扫描的方式,上述代码中astarPath.Scan();为同步扫描。若场景不太大的话同步扫描耗时较低是可以接受的。若耗时过高,造成严重卡顿,可以考虑使用异步烘焙

    private void bakeAStarPath(){//...略StartCoroutine(ScanGraphAsync(astarPath));}IEnumerator ScanGraphAsync(AstarPath astarPath){// 开始异步扫描var progress = astarPath.ScanAsync();foreach (var p in progress){//Debug.Log ("扫描进度: " + p.progress);  yield return null;}Debug.LogError("异步扫描完成!");}

相关文章:

  • 播放进度条小组件
  • C#学习教程(附电子书资料)
  • 413 Payload Too Large 问题定位
  • 【Win32 API】 lstrcpynA()
  • 直接从图片生成 html
  • [Lc] 5.16 One question a day周总结
  • 道路运输企业管理人员考试真题练习
  • 线程和进程
  • CSPM-3级考试成绩已出!附查询流程
  • 多线程八股文(自用)
  • python + flask 做一个图床
  • 【data】上海膜拜数据
  • 多尺度对比度调整
  • 【PhysUnits】4.1 类型级比特位实现解释(boolean.rs)
  • MVVM框架
  • Java百度身份证识别接口实现【配置即用】
  • 芯片生态链深度解析(一):基础材料篇——从砂砾到硅基王国的核心技术突围
  • Deeper and Wider Siamese Networks for Real-Time Visual Tracking
  • Xshell的下载
  • 技术文章:解决汇川MD500系列变频器干扰问题——GRJ9000S EMC滤波器的应用
  • 特朗普政府涉税改法案遭众议院预算委员会否决
  • 美将解除对叙利亚制裁,外交部:中方一贯反对非法单边制裁
  • 牛市早报|4月新增社融1.16万亿,降准今日正式落地
  • 文化润疆|为新疆青少年提供科普大餐,“小小博物家(喀什版)”启动
  • 商务部就开展加强战略矿产出口全链条管控工作应询答记者问
  • A股午后拉升,沪指收复3400点:大金融发力,两市成交超1.3万亿元