优化导航性能

../../_images/nav_optimization.webp

常见的导览相关性能问题可分为以下主题:

  • 为导航网格烘焙解析场景树节点时的性能问题。

  • 烘焙实际导航网格时的性能问题。

  • NavigationAgent 路径查询的性能问题。

  • 实际路径搜索的性能问题。

  • 同步导航地图的性能问题。

在以下部分中可以找到有关如何识别和修复或至少减轻其对影格速率的影响的信息。

解析场景树节点的性能问题

小技巧

喜欢使用边缘尽可能少的简单形状,例如,不要像圆形、球体或圆环那样呈圆形。

优先使用物理碰撞形状而不是复杂的视觉网格作为来源几何体,因为网格需要从GPU复制,并且通常比必要的详细得多。

一般来说,避免使用非常复杂的几何体作为烘焙导览网格的来源几何体。例如,永远不要使用非常详细的视觉网格,因为将其形状解析为数据数组并将其体素化以进行导览网格烘焙将花费很长时间,而不会在最终导览网格上获得真正的质量增益。相反,请使用形状的非常简化的细节等级版本。更好的是,使用非常原始的形状,例如盒子和矩形,它们仅大致覆盖相同的几何形状,但仍然会产生足够好的路径搜寻烘焙结果。

喜欢使用简单的物理碰撞形状而不是视觉网格,作为烘焙导览网格的来源几何。预设情况下,物理形状是非常有限且经过最佳化的形状,可以轻松快速地解析。另一方面,视觉网格的范围可以从简单到复杂。最重要的是,为了存取视觉网格数据,解析器需要从算绘服务器请求网格数据数组,因为视觉网格数据直接储存在GPU上,而不是缓存在CPU上。这需要锁定RenderingServer线程,并且在算绘以多线程运作时会严重影响运作时的影格速率。如果算绘运作单线程,影格率影响可能会更严重,并且网格解析可能会在复杂网格上冻结整个游戏几秒钟。

烘焙导航网格的性能问题

小技巧

在运作时,总是更喜欢使用后台线程来烘焙导览网格。

增加NavigationMesh cell_sizecell_height 以建立较少的体素。

SamplePartitionType 从分水岭更改为单调或分层以获得烘焙性能。

警告

切勿使用节点缩放源几何体以避免精度错误。大多数比例仅适用于视觉,即使缩小比例,在基本比例下非常大的形状仍然需要大量额外的处理。

如果可能的话,在运作时烘焙导览网格应该始终在后台线程中完成。即使是小尺寸的导览网格物体的烘焙时间也可能比挤入单个影格所需的时间长得多,至少在影格率保持在可忍受的水平的情况下是如此。

Complexity of source geometry data parsed from scene tree nodes has big impact on baking performance as everything needs to be mapped to a grid / voxels. For runtime baking performance the NavigationMesh cell size and cell height should be set as high as possible without causing navigation mesh quality problems for a game. If cell size or cell height is set too low the baking is forced to create an excessive amount of voxels to process the source geometry. If the source geometry spans over a very large game world it is even possible that the baking process runs out off memory in the middle and crashes the game. The partition type can also be lowered depending on how complex the games source geometry is to gain some performance. E.g. games with mostly flat surfaces with blocky geometry can get away with the monotone or layers mode that are a lot faster to bake (e.g. because they require no distance field pass).

切勿使用节点缩放源几何。它不仅会导致大量精确度错误(顶点和边配对错误),而且某些缩放仅以视觉形式存在,而不存在于实际解析的数据中。例如,如果网格在编辑器中以视觉方式缩小,例如在MeshInstance上将比例设为0.001,则网格仍然需要巨大且非常复杂的体素网格来处理烘焙。

NavigationAgent 路径查询的性能问题

小技巧

避免在 NavigationAgent 脚本中每一帧都对路径进行不必要的重置和查询。

避免在同一帧里更新所有 NavigationAgent 的路径。

自定义NavigationAgent脚本中的逻辑错误和浪费性操作是导致性能问题的常见原因,例如,请注意每影格重设路径。预设情况下,NavigationAgents经过最佳化,仅在目标位置变更、导览地图变更或被迫远离所需路径距离时查询新路径。

例如,当AI应移动到玩家时,目标位置不应每影格都设定为玩家位置,因为这会每影格查询新路径。相反,应该比较从目前目标位置到玩家位置的距离,并且只有当玩家移动得太远时才应该设定新的目标位置。

不要预先检查每个画面是否可以到达目标位置。看似无害的检查实际上相当于幕后昂贵的路径查询。如果计划无论如何都要请求新路径(如果位置可达),则应直接查询路径。透过查看返回路径的最后一个位置,如果该位置距检查位置处于“可到达”距离,则它会回答“该位置是否可到达?”问题。这避免了对同一个NavigationAgent每影格执行两次完整路径查询的等效操作。

将导览代理程序的总数分割为更新组或使用随机定时器,以便它们不会在同一影格中全部请求新路径。

实际路径搜索的性能问题

小技巧

透过减少多边形和边的数量来优化过于详细的导览网格。

实际路径搜寻的成本与导览网格多边形和边缘的数量直接相关,而不是与游戏世界的实际大小相关。如果一个巨大的游戏世界使用非常优化的导览网格,只有少数多边形覆盖大面积,那么性能应该是可以接受的。如果游戏世界被分割成非常小的导览网格,每个导览网格都有微小的多边形(如TileMap),则寻路性能将会降低。

一个常见问题是当路径查询中无法到达目标位置时效能突然下降。这种性能下降是“正常的”,是导览网格太大、未优化的结果,需要搜寻大量多边形和边缘。在可以快速到达目标位置的正常路径搜寻中,一旦到达该位置,寻路就会提前退出,这可以暂时隐藏这种优化不足的情况。如果无法到达目标位置,则寻路必须对可用多边形进行更长的搜索,以确认该位置绝对无法到达。

导航地图同步的性能问题

小技巧

合并导览尽可能透过顶点而不是边连接来网格化多边形。

当对导览网格或导览区域进行变更时,导览服务器需要同步导览地图。根据导览网格的复杂性,这可能需要大量时间,这可能会影响影格速率。

导览服务器透过顶点或边连接合并导览网格。当两条不同边的两个顶点落在同一地图网格单元中时,就会发生以顶点合并。这是一个相当快速且低成本的操作。对于所有尚未合并的边,按边连接进行合并发生在第二遍。透过距离和角度检查所有自由边缘是否有可能的边缘连接,这是相当昂贵的。

因此,除了具有尽可能少的多边形边的一般规则之外,还应透过顶点预先合并尽可能多的边,以便只留下少量边用于成本更高的边连接计算。调试导览性能摄像头可用于取得有关可用多边形和边的数量以及其中有多少未合并或未按顶点合并的统计数据。如果顶点合并和边连接之间的比率相差很大(顶点应该明显更高),则导览网格会正确建立或放置得非常低效。