#路径查找 #导航 #bevy #bevy-ecs #ryot #2d-game #tiled-2d-games

ryot_pathfinder

为Bevy 2D提供专门的路径查找功能,对于游戏中的动态导航和移动至关重要

2个版本

0.2.3 2024年4月29日
0.2.2 2024年4月29日

#1315 in 游戏开发


用于 2 crates

AGPL-3.0-only

2MB
2K SLoC

Ryot PathFinder

License Crates.io Downloads Docs Discord

什么是Ryot PathFinder

Ryot PathFinder是针对Bevy的高性能、异步实现的路径查找。它旨在与Bevy的ECS无缝协作,为需要动态导航的游戏和模拟提供强大的路径查找功能。尽管它针对2D网格环境进行了优化,但可以轻松扩展以满足特定的游戏需求和开放世界场景。它依赖于Ryot Core,并与Ryot Tiled具有集成。

路径查找

路径查找是游戏开发中的基本概念,使实体能够有效地在复杂环境中导航。它涉及在两点之间找到最短路径,考虑障碍物,并根据各种标准优化路线。路径查找算法对于创建引人入胜的游戏体验至关重要,使角色能够智能地移动并有效地与游戏世界互动。

在此背景下,Ryot PathFinder为在Bevy项目中实现路径查找系统提供了一个全面的解决方案,提供了一个灵活且可扩展的框架来处理导航逻辑。通过利用异步操作和无缝的Bevy集成,开发者可以创建动态的路径查找系统,这些系统可以适应不断变化的游戏条件和玩家交互。

PathFinder使用Pathfinding作为底层路径查找库。对于2D默认实现,它使用A*算法来计算两点之间的最短路径。

功能

  • 无缝Bevy集成:构建时与Bevy的ECS紧密协作,提供流畅的集成并确保与Bevy事件系统的兼容性。
  • 异步操作:利用异步任务以保持高性能和响应性,特别适用于路径查找需求广泛的场景。
  • 2D优化:特别针对2D网格导航进行了定制,为基于瓦片和开放世界游戏环境提供了强大的工具。
  • 可扩展架构:设计用于灵活,允许开发者扩展和自定义路径查找逻辑,以满足特定的游戏需求。

功能

此包包含一个可选功能,ryot_tiled,该功能与Ryot Tiled包集成,以支持贴图2D特定的路径查找系统。该功能扩展了路径查找功能,使其能够无缝地与贴图地图一起工作,为使用基于贴图的布局的游戏添加了有价值的功能。

基本设置

在设置路径查找器之前,让我们了解路径查找器的两个核心概念:Pathable<P>Navigable<N>

可通行

Pathable特性表示世界中的位置。它用于计算两点之间的路径。特性要求实现generate方法,该方法基于(x, y, z)返回一个可通行的位置,一个坐标方法,它返回可通行位置的坐标,以及一个path_to方法,该方法计算到另一个可通行位置的路。

可导航

Navigable特性属于ryot_core,用于确定一个点是否可导航。目前,它在维度空间中有两种导航条件:is_walkableblocks_sight。特性要求实现is_walkableblocks_sight方法,这些方法根据导航条件返回一个布尔值。特性有一个append方法,该方法将可导航值附加到另一个可导航值。

它还需要实现is_default方法,该方法返回true,如果该实现对应于默认值(用于跳过不必要的计算)。

Bevy

要集成ryot_pathfinder,您需要将一个可通行添加到您的Bevy应用程序中。这是通过在您的Bevy应用程序构建器上调用add_pathable方法来完成的。可通行由Pathable和Navigable实现的一对表示。

以下是一个基本示例,其中包含来自ryot_tiled的预定义Pathable和Navigable实现

use bevy::prelude::*;
use ryot_pathfinder::prelude::*;
use ryot_core::prelude::*;
use ryot_tiled::prelude::*;

fn setup(mut commands: Commands) {
    commands.spawn(PathFindingQuery::<TilePosition>::default());
}

fn build_app(app: &mut App) -> &mut App {
    app
        .add_plugins(DefaultPlugins)
        .add_pathable::<TilePosition, Flags>()
}

组件

PathFindingQuery有三个主要组件

PathFindingQuery<P>

此组件附加到需要路径查找计算的实体。它指定路径查找算法的参数

  • to:目标位置。
  • cardinal_cost:在正方向上的移动成本。
  • diagonal_cost:在斜方向上的移动成本。
  • success_distance:被认为是成功路径查找计算的目标位置的距离。
  • timeout:路径查找算法在返回None之前可以运行的最大时间(以秒为单位)。

它是公共API的一部分,应由用户用于触发路径查找计算。

PathFindingTask<P>

此组件附加到当前正在计算路径查找算法的实体。它持有将返回路径结果的future(或任务)。它是ryot_pathfinder内部的,不能由用户使用。

Path<P>

此组件附加到已完成路径查找计算的实体。它持有路径查找计算的结果,实体可以跟随的实际路径到达目标。

它是公共API的一部分,应由用户用于沿着路径移动实体。

工作流程

流程分为四个步骤

  1. PathFindingQuery<P>被添加到实体中,指定路径查找算法的参数。
  2. PathFindingQuery<P> 被系统 trigger_path_finding_tasks 消耗,该系统创建一个 PathFindingTask<P> 并将其附加到实体上。
  3. PathFindingTask<P> 异步执行,一旦完成,系统 handle_path_finding_tasks 创建一个 Path<P> 组件并将其附加到实体上。
  4. 现在,用户可以消费 Path<P> 来沿着路径移动实体。

要更好地理解 PathFindingQuery<P>PathFindingTask<P>Path<P> 之间的交互,请查看下面的图示:

示例

根据您的需求选择一个示例来运行,例如处理多个实体或处理障碍物

cargo run --example example_name

将 example_name 替换为您要运行的示例的名称。

理解示例

库中包含的每个示例都展示了路径查找系统的不同方面

  • 基础:演示了最简单的路径查找形式。
  • 多个:处理多个角色同时导航。
  • 障碍物:在路径查找计算中集成静态障碍物。

探索高级场景

随着您越来越熟练,探索更复杂的示例,如压力测试或与基于瓦片的系统集成

  • 瓦片*:使用 ryot_tiled 功能在瓦片地图上执行路径查找,使用 TilePosition 和 Flags。
  • 压力测试*:评估路径查找器在高负载条件下的性能。

这些示例需要启用 "ryot_tiled" 功能。

构建您自己的场景

利用 ExampleBuilder 来自定义和创建定制的路径查找示例/测试场景

fn main() {
    // ExampleBuilder::<P/* custom pathable type */, N/* custom navigable type */>::new()
    //     .with_grid_size(/* custom dimension of a squared grid, default 10 */)
    //     .with_n_entities(/* number of actors to spawn, default 10 */)
    //     .with_n_obstacles(/* number of obstacles to spawn, default 0 */)
    //     .with_max_distance(/* maximum distance to calculate pathfinding, default 10 */)
    //     .with_sleep(/* sleep time (ms) between consuming pathfinding results, default 100 */)
    //     .with_navigable(/* custom navigable (N) value for obstacles, default N::default() */)
    //     .with_query_builder(/* custom query builder, default PathFindingQuery::new(pos).with_success_distance(0.) */)
    //     .drawing_app()
    //     .run();
}

基准测试

包含性能基准测试,以提供有关 crate 效率的见解。可以运行基准测试 bench 以在各种条件下评估性能

cargo bench --features ryot_tiled

结果

测试名称 大小 时间(ns/iter) 可变性(± ns) 每秒迭代次数(iters/s)
bench_2_sized_path_finding 2 137 2 7,299,270
bench_3_sized_path_finding 3 166 2 6,024,096
bench_5_sized_path_finding 5 285 6 3,508,772
bench_10_sized_path_finding 10 1,131 73 884,148
bench_15_sized_path_finding 15 3,272 188 305,709
bench_20_sized_path_finding 20 7,139 691 140,088
bench_with_obstacles 20 40,044 4,442 24,973
bench_30_sized_path_finding 30 21,406 831 46,726
bench_50_sized_path_finding 50 81,027 5,558 12,343
bench_75_sized_path_finding 75 225,945 86,525 4,424
bench_100_sized_path_finding 100 445,268 241,426 2,246

这种 README 格式清楚地划分了功能、示例用法和基准测试,为任何希望将 ryot_pathfinder crate 集成到其项目中的用户提供了一份全面的指南。

依赖关系

~18–34MB
~524K SLoC