#amethyst #navigation #agent #engine #driver #nav #game

amethyst-navigation

Amethyst引擎的导航模块

1个不稳定版本

0.1.0 2019年8月13日

#2268游戏开发

Apache-2.0/MIT

9KB

Amethyst Navigation

基于Nav-mesh的2D和3D导航工具集,用于Amethyst游戏引擎

目录

  1. 关于
  2. 清单
  3. 设置
  4. 构建Nav Mesh
  5. 创建代理
  6. 设置代理目的地
  7. 自定义代理驱动

关于

在游戏开发过程中,您可能会希望允许您的角色在世界中找到路径并沿其移动。此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