2个版本
0.2.3 | 2024年4月29日 |
---|---|
0.2.2 | 2024年4月29日 |
#1315 in 游戏开发
用于 2 crates
2MB
2K SLoC
Ryot PathFinder
什么是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_walkable
和blocks_sight
。特性要求实现is_walkable
和blocks_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的一部分,应由用户用于沿着路径移动实体。
工作流程
流程分为四个步骤
PathFindingQuery<P>
被添加到实体中,指定路径查找算法的参数。PathFindingQuery<P>
被系统trigger_path_finding_tasks
消耗,该系统创建一个PathFindingTask<P>
并将其附加到实体上。PathFindingTask<P>
异步执行,一旦完成,系统handle_path_finding_tasks
创建一个Path<P>
组件并将其附加到实体上。- 现在,用户可以消费
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