2个版本
0.2.3 | 2024年5月6日 |
---|---|
0.2.2 | 2024年4月29日 |
#895 in 游戏开发
在ryot_internal中使用
120KB
2K SLoC
Ryot Ray Casting
什么是Ryot Ray Casting?
Ryot Ray Casting利用光线投射的概念,为Bevy提供强大的光线投射系统。它设计用于与Bevy的ECS无缝协作,使开发者能够在其游戏和模拟中实现基于轨迹的高级机制,这些机制需要进行精确的直线轨迹计算,并支持障碍物、视线和其他复杂交互。尽管它针对2D网格环境进行了优化,但它可以轻松扩展以满足特定的游戏需求和开放世界场景。它是Ryot框架的一部分,依赖Ryot Core和Ryot Utils。
光线投射和轨迹
光线投射是游戏开发中的基本概念,它使复杂的游戏机制(如抛体运动、视线、战争迷雾、碰撞检测等)成为可能。光线投射是一种通过在二维或三维环境中追踪光线来模拟轨迹的技术,在追踪过程中检测碰撞和交互。它广泛应用于游戏,以实现逼真的物理、光照效果和AI行为,为创建引人入胜的游戏体验提供了一种灵活的工具。
在Ryot Ray Casting的上下文中,它为在Bevy项目中实现光线投射系统提供了一种全面的解决方案,提供了一个灵活且可扩展的框架来处理光线投射逻辑。通过利用ECS架构和与Bevy的无缝集成,开发者可以创建能够适应不断变化的游戏条件和玩家交互的动态光线投射系统。
Ryot RayCasting使用Bevy RayCast3d作为底层光线投射库,适用于2D和3D环境。
功能
- 无缝Bevy集成:与Bevy的ECS紧密结合,提供流畅的集成并确保与Bevy的事件系统兼容。
- 光线投射支持:利用光线投射来模拟轨迹,实现精确的碰撞检测和与障碍物的交互。
- 二维优化:专门针对基于二维网格的导航,为基于瓦片和开放世界游戏环境提供强大的工具。
- 可扩展架构:设计为灵活,允许开发者扩展和自定义射线投射逻辑,以适应特定的游戏需求。
基本设置
在设置射线投射框架之前,让我们了解核心概念:Point
、RayCastingPoint
、Navigable
、RadialArea<P>
和Perspective<P>
。
Point
Point 特性表示世界中的位置。它是 Ryot 生态系统的一个核心概念,允许您将您自己的世界表示与 Ryot 及其空间算法集成。
RayCastingPoint
Point 特性的扩展,RayCastingPoint 特性表示世界中可以用于评估射线投射的位置。它用于生成空间中给定点的边界框,用于检查点是否与射线投射冲突。此软件包主要使用 aabb3d(轴对齐边界框)来表示空间中点的边界框,并使用射线投射 aabb 交集来检查点是否在射线内。
Navigable
Navigable 特性属于 ryot_core
,用于确定点是否可导航。它用于确定一个角色是否可以通过世界中的特定点,例如,该点是否可步行。
目前,Navigable 有两个标志:is_walkable
和 is_flyable
。第一个用于确定一个角色是否可以通过一个点,第二个用于确定一个角色是否可以通过一个点飞行。
RadialArea
RadialArea 结构是对游戏世界中一个区域的描述性表示。它只包含原始的可复制类型,实现 Hash,其主要目的是用作 Perspectives 的描述性表示,允许缓存复杂的角度计算并未来重用。
Perspective
Perspective 结构是从给定观察者点的一个视角的表示。它包含一个遍历数组,这些是 RayCast3d 和射线遍历区域的元组。它用于表示在确定场景/条件下可以从观察者视角投射的所有射线。
Bevy
要集成 ryot_ray_casting
,您需要在 Bevy 应用中添加射线投射。这是通过调用 add_ray_casting<T, P, N>
实现的,其中 T
是表示射线投射上下文的标记类型,P
是 RayCastingPoint 类型,而 N
是 Navigable 类型。此方法是 Bevy 应用构建器上的构建方法。
以下是一个基本示例
use bevy::prelude::*;
use ryot_core::prelude::*;
use ryot_ray_casting::prelude::*;
fn setup<P: RayCastingPoint + 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 ray casting.
commands.spawn(RayCasting::<(), P>::default());
}
fn build_app<P: RayCastingPoint + Component>(app: &mut App) -> &mut App {
app
.add_plugins(DefaultPlugins)
.add_ray_casting::<(), P, Flags>()
}
组件
此软件包有两个主要的 ECS 组件
RayCasting<T, P>
此结构表示游戏世界中的射线投射。它是一个可以附加到 ECS 实体上的组件,用于表示实体给定的上下文 T 的射线投射请求。
此组件附加到需要射线投射计算的实体上。它指定射线投射评估的参数
- 区域:表示将要投射射线的平面的径向区域。
- 共享:射线传播将与之共享的实体。
- 条件:基于可导航类型,平面点 P 必须满足的条件,以避免与投射的射线冲突。
- 参数:一组可以用于自定义射线投射计算的参数。
- max_collisions:光线投射在停止传播之前可以发生的最大碰撞次数。
- reversed:如果光线应该以相反的顺序(从末端到起始点)进行分析。
- execution_type:光线投射应该具有的执行类型:一次或基于时间的。
- last_executed_at:光线投射上次执行的时间,一个标志,用于确定是否应该再次执行。
它是公共API的一部分,应由用户用于触发光线投射计算。
当此组件不再满足与其ExecutionType相关的执行要求时,它会自动删除。
RayPropagation<T, P>
此组件附加到已完成光线投射计算的实体上。它包含光线投射评估的结果,以及光线如何在给定的平面上传播,表示为
- collisions:光线与请求的平面之间的碰撞,这意味着这些点不可导航。
- position:碰撞发生的位置。
- distance:光线起源到碰撞点的距离。
- previous_position:碰撞发生之前光线接触的先前位置。
- pierced:如果碰撞被穿透或未被穿透,这意味着光线传播在碰撞后继续。
- area_of_interest:光线投射的兴趣区域,所有光线投射传播的点,这意味着光线影响这些点上的世界。
此组件附加到已完成光线投射计算的实体上。它是公共API的一部分,应由用户用于检查光线传播。
系统
光线投射框架由三个主要系统组成
update_intersection_cache<T, P>
:此系统更新由RayCasting<T, P>组件中存在的径向区域表示的交集缓存。此缓存用于加快光线投射计算,避免重新计算已经计算的光线投射aabb交集。process_ray_casting<T, P, N>
:光线投射框架的主系统,它执行ECS中的光线投射请求,计算光线传播并将结果附加到实体上。share_results<T, P>
:此系统将实体的光线传播结果与光线投射可以共享的实体共享。
还有两个系统是清理过程的一部分
remove_stale_results<T, P>
:此系统从不再具有RayCasting<T, P>组件的实体中删除RayPropagation<T, P>。remove_stale_requests<T, P>
:此系统删除不再有效的RayCasting<T, P>请求。
示例
根据您的需求选择一个示例来运行,例如处理多个实体或处理障碍物。
cargo run --example example_name --features stubs
将example_name替换为您希望运行的示例的名称。
理解示例
库中包含的每个示例都展示了光线投射系统的不同方面。
- 基本:演示了一个基本完整的光线投射用例,包括障碍物和不同的径向区域。
- 压力测试:评估在高负载条件下光线投射的性能。
构建您自己的场景
利用ExampleBuilder
来自定义和创建定制的光线投射示例/测试场景。
fn main() {
// ExampleBuilder::<T /* Contextual Marker */, P /* RayCastingPoint */, N /* Navigable */>::new()
// .with_ray_castings(/* array of (ray casting, count) tuples, containing the ray casting 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();
}
基准测试
性能基准测试被包含在内,以提供对crate效率的洞察。可以通过运行基准测试来评估在不同条件下的性能。
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_ray_casting
crate集成到他们项目中的任何人提供了一个全面的指南。
依赖项
~17–59MB
~1M SLoC