1个不稳定版本
0.1.0 | 2019年8月13日 |
---|
#2268 在 游戏开发
9KB
Amethyst Navigation
基于Nav-mesh的2D和3D导航工具集,用于Amethyst游戏引擎
目录
关于
在游戏开发过程中,您可能会希望允许您的角色在世界中找到路径并沿其移动。此Amethyst插件为您提供使用导航网格技术构建导航网格(描述可通行区域的特殊网格)以及创建代理并设置其目的地以跟随的机会。您的目的地可以是世界空间中的点或另一个代理实体。
清单
Cargo.toml
[dependencies]
amethyst-navigation = "0.1"
设置
在 amethyst-navigation
之前工作,您必须安装两个系统
NavAgentMaintainSystem
以允许代理找到通往其目的地的路径。SimpleNavDriverSystem
以允许代理在路径上执行简单移动。
use amethyst_navigation::prelude::*;
let game_data = GameDataBuilder::default()
// ...
// INSTALL ENGINE BUNDLES HERE
// ...
// nav agent maintainment system allows agents find paths to their destinations.
.with(NavAgentMaintainSystem::default(), "nav-agent-maintain", &[])
// simple nav driver system allows agents with `SimpleNavDriverTag` to perform simple
// movement along path.
.with(SimpleNavDriverSystem, "simple-nav-driver", &[]);
构建Nav Mesh
导航网格是一种特殊的网格,允许代理找到从一点到另一点的最短路径,这些点始终位于给定的导航网格上。
use amethyst_navigation::prelude::*;
// create nav mesh vertices and triangles.
// in future this will be loaded from asset.
let vertices: Vec<NavVec3> = vec![
(50.0, 50.0).into(), // 0
(500.0, 50.0).into(), // 1
(500.0, 100.0).into(), // 2
(100.0, 100.0).into(), // 3
(100.0, 300.0).into(), // 4
(700.0, 300.0).into(), // 5
(700.0, 50.0).into(), // 6
(750.0, 50.0).into(), // 7
(750.0, 550.0).into(), // 8
(50.0, 550.0).into(), // 9
];
let triangles: Vec<NavTriangle> = vec![
(1, 2, 3).into(), // 0
(0, 1, 3).into(), // 1
(0, 3, 4).into(), // 2
(0, 4, 9).into(), // 3
(4, 8, 9).into(), // 4
(4, 5, 8).into(), // 5
(5, 7, 8).into(), // 6
(5, 6, 7).into(), // 7
];
// build a nav mesh and register it so agents can traverse it.
let mesh = NavMesh::new(vertices, triangles).unwrap();
world.write_resource::<NavMeshesRes>().register(mesh);
创建代理
代理是一种实体类型,在导航网格上两点之间寻找和跟随路径。每个代理实体必须具有 NavAgent
组件和一个驱动组件。目前只有一个驱动程序 - SimpleNavDriverTag
标记代理执行沿路径的简单移动。将来将提供更多具有不同行为的驱动程序,但用户可以轻松创建自己的驱动程序。
use amethyst_navigation::prelude::*;
let mut agent = NavAgent::new((x as f64, y as f64).into());
agent.speed = speed;
world
.create_entity()
// this entity is an agent.
.with(agent)
// this entity will do a simple movement along path.
.with(SimpleNavDriverTag)
.build();
设置代理目的地
use amethyst_navigation::prelude::*;
// get mesh identifier from registry.
let mesh = meshes.meshes_iter().nth(0).unwrap().id();
// set player agent destination.
agent.set_destination(
// we can also select another agent to follow.
NavAgentTarget::Point((x as f64, y as f64).into()),
// use best quality point on nav mesh query.
NavQuery::Accuracy,
// use best quality of path finding.
NavPathMode::Accuracy,
mesh,
);
自定义代理驱动
SimpleNavDriverSystem
具有您可以想象到的最简单的移动代码。您可以创建自己的驱动程序系统并更改代理行为,例如添加避障。
注意:请记住创建驱动组件标记以标记使用该驱动程序的代理。
use amethyst_navigation::prelude::*;
pub struct SimpleNavDriverSystem;
impl<'s> System<'s> for SimpleNavDriverSystem {
type SystemData = (
Read<'s, Time>,
WriteStorage<'s, NavAgent>,
ReadStorage<'s, SimpleNavDriverTag>,
);
fn run(&mut self, (time, agents, drivers): Self::SystemData) {
let delta_time = time.delta_seconds() as f64;
if delta_time <= 0.0 {
return;
}
for (agent, _) in (&mut agents, &drivers).join() {
if let Some(path) = agent.path() {
if let Some((target, _)) = NavMesh::path_target_point(
path,
agent.position,
agent.speed.max(agent.min_target_distance.max(0.0)) * delta_time,
) {
let diff = target - agent.position;
let dir = diff.normalize();
agent.position = agent.position
+ dir * (agent.speed.max(0.0) * delta_time).min(diff.magnitude());
agent.direction = diff.normalize();
}
}
}
}
}
依赖项
~15MB
~291K SLoC