#trajectory #bevy #ryot #ray-cast #game-mechanics

已删除 ryot_trajectories

为Bevy实现轨迹功能,对视线、迷雾、复杂碰撞等交互式游戏机制至关重要

1 个不稳定版本

0.2.2 2024年5月6日

#12#ryot


用于 ryot_tiled

AGPL-3.0-only

120KB
2K SLoC

Ryot 轨迹

License Crates.io Downloads Docs Discord

什么是Ryot轨迹?

Ryot轨迹利用光线投射的概念,为Bevy提供强大的轨迹系统。它旨在与Bevy的ECS无缝协作,使开发者能够在需要精确轨迹计算、支持障碍物、视线和其他复杂交互的游戏和模拟中实现基于轨迹的高级机制。尽管它针对2D网格环境进行了优化,但它可以轻松扩展以满足特定的游戏需求和开放世界场景。它是Ryot框架的一部分,依赖于Ryot CoreRyot Utils

光线投射和轨迹

轨迹是游戏开发中的基本概念,使复杂的游戏机制,如抛物线运动、视线、迷雾、碰撞检测等成为可能。光线投射是一种通过在2D或3D环境中追踪光线来模拟轨迹的技术,并在途中检测碰撞和交互。它在游戏中被广泛用于实现逼真的物理、照明效果和AI行为,为创建引人入胜的游戏体验提供了一种通用的工具。

在Ryot轨迹的上下文中,为在Bevy项目中实现轨迹系统提供了一个全面的解决方案,提供了一个灵活且可扩展的框架来处理轨迹逻辑。通过利用ECS架构和与Bevy的无缝集成,开发者可以创建动态的轨迹系统,以适应不断变化的游戏条件和玩家交互。

轨迹使用Bevy RayCast3d作为底层光线投射库,用于2D和3D环境。

功能

  • 无缝Bevy集成:旨在与Bevy的ECS协同工作,提供平滑的集成并确保与Bevy的事件系统的兼容性。
  • 光线投射支持:利用光线投射模拟轨迹,实现精确的碰撞检测和与障碍物的交互。
  • 2D优化:特别针对2D网格导航进行优化,为基于瓦片和开放世界游戏环境提供强大的工具。
  • 可扩展架构:设计用于灵活,允许开发者扩展和自定义轨迹逻辑以适应特定的游戏需求。

基本设置

在设置轨迹框架之前,让我们理解核心概念: PointTrajectoryPointNavigableRadialArea<P>Perspective<P>Trajectory<T, P>

Point

Point 特性代表世界中的位置。它是 Ryot 生态系统的核心概念,允许您将您自己的世界表示与 Ryot 及其空间算法集成。

TrajectoryPoint

Point 特性的扩展,TrajectoryPoint 特性代表世界中可以用于计算轨迹的位置。它用于生成给定空间中点的边界框,用于检查点是否与射线投射相交。这个包主要使用 aabb3d(轴对齐边界框)来表示空间中点的边界框,并使用射线投射 aabb 交集来检查点是否在轨迹内或不在。

Navigable

Navigable 特性属于 ryot_core,用于确定一个点是否可导航。它用于确定演员是否可以穿越世界中的特定点,例如这个点是否可通行。

目前,Navigable 有两个标志:is_walkableis_flyable。第一个用于确定演员是否可以穿越点,第二个用于确定演员是否可以穿越点。

RadialArea

RadialArea 结构是游戏世界中区域的描述性表示。它只包含原始和可复制的类型,实现了 Hash,其主要目的是用作视角的描述性表示,允许缓存复杂计算的视角并在将来重用。

Perspective

Perspective 结构是从给定的观众点获取的视角的表示。它包含一个遍历数组,遍历是 RayCast3d 和射线穿越的区域元组。它用于表示观众可以在特定场景/条件下从空间中的给定点看到的所有轨迹。

Trajectory

轨迹结构是游戏世界中轨迹的表示。它是可以附加到 ECS 中的实体上的组件,用于表示实体的轨迹请求。它包含轨迹的径向区域、轨迹必须满足的条件、可以共享轨迹的实体,以及一组可以用于自定义轨迹计算的参数。

Bevy

要集成 ryot_trajectories,您需要将轨迹添加到您的 Bevy 应用中。这是通过调用 add_trajectory<T, P, N> 来完成的,其中 T 是表示轨迹上下文的标记类型,P 是轨迹点类型,N 是可导航类型。此方法是 Bevy 应用构建器上的构建器方法。

以下是一个基本示例

use bevy::prelude::*;
use ryot_core::prelude::*;
use ryot_trajectories::prelude::*;

fn setup<P: TrajectoryPoint + Component>(mut commands: Commands) {
    // here we use () as a marker, but in a real scenario you should use a marker type
    // that properly represents the context of the trajectory.
    commands.spawn(Trajectory::<(), P>::default());
}

fn build_app<P: TrajectoryPoint + Component>(app: &mut App) -> &mut App {
    app
        .add_plugins(DefaultPlugins)
        .add_trajectory::<(), P, Flags::default()>()
}

组件

这个包有两个主要的 ECS 组件

TrajectoryRequest<T, P>

此组件连接到需要轨迹计算的实体。它指定了轨迹算法的参数

  • 区域:表示轨迹将覆盖的径向区域。
  • 共享给:轨迹可以与之共享的实体。
  • 条件:轨迹必须满足的条件,基于可导航类型和位置。
  • 参数:一组可用于自定义轨迹计算的参数。
    • 最大碰撞次数:在这个轨迹中发射的射线可以有的最大碰撞次数。
    • 反向:如果轨迹应以反向顺序(从末端到起点)进行分析。
    • 执行类型:轨迹应具有的执行类型:一次或基于时间。
  • 上次执行时间:轨迹上次执行的时间,一个标志,用于确定是否再次执行轨迹。

它是公共API的一部分,应由用户用于触发轨迹计算。

轨迹结果<T, P>

此组件连接到已完成轨迹计算的实体。它包含轨迹计算的结果,表示为

  • 碰撞:轨迹与世界的碰撞,意味着在这些点上轨迹不可导航。
    • 位置:碰撞发生的位置。
    • 距离:从轨迹起点到碰撞的距离。
    • 前一个位置:碰撞前的轨迹位置。
    • 穿透:碰撞是否穿透,意味着轨迹在碰撞后继续。
  • 感兴趣区域:轨迹的感兴趣区域,意味着在这些点上轨迹是可导航的,可以影响世界。

此组件连接到已完成轨迹计算的实体。它是公共API的一部分,应由用户用于检查轨迹结果。

系统

轨迹框架由三个主要系统组成

  1. update_intersection_cache<T, P>:此系统更新由TrajectoryRequest<T, P>组件中存在的径向区域表示的交叉缓存。此缓存用于加速轨迹计算,避免重新计算已计算过的射线投射aabb交叉。
  2. process_trajectories<T, P, N>:轨迹框架的主系统,它执行ECS中存在的轨迹请求,计算轨迹并将结果附加到实体上。
  3. share_results<T, P>:此系统将实体的轨迹结果与轨迹可以共享的实体共享。

还有两个系统是清理过程的一部分

  1. remove_stale_results<T, P>:此系统删除不再与轨迹请求关联的轨迹结果。
  2. remove_stale_trajectories<T, P>:此系统删除不再有效的轨迹请求。

示例

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

cargo run --example example_name --features stubs

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

理解示例

库中包含的每个示例都展示了轨迹系统的不同方面

  • 基本:演示了一个基本的完整轨迹用例,包括障碍物和不同的径向区域。
  • 压力测试:评估轨迹在高负载条件下的性能。

构建自己的场景

利用ExampleBuilder来自定义和创建定制的轨迹示例/测试场景

fn main() {
    // ExampleBuilder::<T /* Contextual Marker */, P /* TrajectoryPoint */, N /* Navigable */>::new()
    // .with_trajectories(/* array of (trajectory, count) tuples, containing the trajectories to be instantiated and how many */)
    //  .with_obstacles(/* number of obstacles to be instantiated */)
    //      .app() // basic app with visual capabilities
    //      /* add your custom systems, plugins and resources here */
    //      .run();
}

基准测试

包括性能基准测试,以提供对库效率的洞察。可以在各种条件下运行基准测试来评估性能

cargo bench --features stubs

结果

轨迹系统有三个主要基准:创建轨迹、执行轨迹和检查可导航点与轨迹。基准覆盖不同的场景,如线性、扇形和圆形区域,以及不同的范围值。

以下表格提供了轨迹系统基准测试结果的概述

创建

测试名称 类型 范围(距离) 时间(ns/iter) 可变性(± ns) 每秒迭代次数(iters/s)
create_linear_range_10 线性 10 143 3 6,993,007
create_linear_range_100 线性 100 821 114 1,218,027
create_linear_range_255 线性 255 1,337 197 747,951
create_45_degrees_sector_range_10 径向_45 10 1,160 12 862,069
create_45_degrees_sector_range_100 径向_45 100 17,142 409 58,358
create_45_degrees_sector_range_255 径向_45 255 29,580 830 33,822
create_90_degrees_sector_range_10 径向_90 10 2,734 112 365,632
create_90_degrees_sector_range_100 径向_90 100 34,297 883 29,159
create_90_degrees_sector_range_255 径向_90 255 59,535 2,329 16,802
create_circular_range_3 圆形 3 1,871 28 534,759
create_circular_range_5 圆形 5 4,724 74 211,640
create_circular_range_10 圆形 10 9,819 292 101,844
create_circular_range_25 圆形 25 38,055 769 26,284
create_circular_range_50 圆形 50 81,998 2,237 12,195
create_circular_range_100 圆形 100 143,330 2,569 6,979
create_circular_range_255 圆形 255 277,505 40,670 3,605

执行

测试名称 类型 范围(距离) 时间(ns/iter) 可变性(± ns) 每秒迭代次数(iters/s)
execute_linear_range_10 线性 10 95 1 10,526,316
execute_linear_range_100 线性 100 1,169 32 855,048
execute_linear_range_255 线性 255 2,783 349 359,323
execute_45_degrees_sector_range_10 径向_45 10 602 6 1,660,798
execute_45_degrees_sector_range_100 径向_45 100 23,884 666 41,866
execute_45_degrees_sector_range_255 径向_45 255 60,248 897 16,600
execute_90_degrees_sector_range_10 径向_90 10 1,227 29 815,073
execute_90_degrees_sector_range_100 径向_90 100 47,821 972 20,914
execute_90_degrees_sector_range_255 径向_90 255 121,197 25,467 8,250
execute_circular_range_3 圆形 3 920 77 1,086,957
execute_circular_range_5 圆形 5 2,034 123 491,699
execute_circular_range_10 圆形 10 5,074 215 197,203
execute_circular_range_25 圆形 25 27,759 923 36,020
execute_circular_range_50 圆形 50 92,329 1,405 10,828
execute_circular_range_100 圆形 100 199,025 3,846 5,025
execute_circular_range_255 圆形 255 812,311 28,281 1,231

可导航碰撞

测试名称 类型 范围(距离) 时间(ns/iter) 可变性(± ns) 每秒迭代次数(iters/s)
check_1million_obstacles_against_line_range_15 线性 15 44 1 22,727,273
check_1million_obstacles_against_line_range_50 线性 50 267 8 3,745,318
check_1million_obstacles_against_line_range_100 线性 100 585 15 1,709,402
check_1million_obstacles_against_line_range_255 线性 255 1,699 38 588,581
check_1million_obstacles_against_45_degrees_sector_range_15 径向_45 15 612 21 1,633,987
check_1million_obstacles_against_45_degrees_sector_range_50 径向_45 50 6,660 1,812 150,150
check_1million_obstacles_against_45_degrees_sector_range_100 径向_45 100 17,077 612 58,545
check_1million_obstacles_against_45_degrees_sector_range_255 径向_45 255 53,496 8,487 18,692
check_1million_obstacles_against_90_degrees_sector_range_15 径向_90 15 1,339 117 746,808
check_1million_obstacles_against_90_degrees_sector_range_50 径向_90 50 13,385 405 74,706
check_1million_obstacles_against_90_degrees_sector_range_100 径向_90 100 40,414 1,383 24,742
check_1million_obstacles_against_90_degrees_sector_range_255 径向_90 255 108,612 4,525 9,209
check_1million_obstacles_against_circle_range_15 圆形 15 5,136 55 194,748
check_1million_obstacles_against_circle_range_50 圆形 50 67,538 2,029 14,810
check_1million_obstacles_against_circle_range_100 圆形 100 161,176 3,945 6,206
check_1million_obstacles_against_circle_range_255 圆形 255 437,340 10,785 2,287

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

依赖项

~17–59MB
~1M SLoC