AgentPathNavigator

three

キャラクター位置・現在ウェイポイント・速度上限を平面移動意図(方向・希望速度・ウェイポイント・距離)へ変換する。

カテゴリAI ビヘイビア
依存ティアthree
関連モジュールなし
デモシーンpathfinding · 経路探索 ↓
このモジュールだけ取得
modules/behavior/AgentPathNavigator.js

内部依存もまとめて、相対ディレクトリ構造を保ってコピーします。

経路探索

純ロジック

クリックで目標移動 · Shift+クリックで壁の切替。

ソース

import { Vector3 } from 'three';
import { clamp } from '../math/ScalarUtils.js';
import { DEFAULT_WORLD_BASIS } from '../math/WorldBasis.js';
import { toVec3 } from '../math/Vector3Utils.js';

const EPS = 1e-6;

function neutralIntent({ waypoint = null }) {
  const target = waypoint ? toVec3(waypoint) : null;
  return {
    waypoint: target ? target.clone() : null,
    direction: new Vector3(0, 0, 0),
    desiredSpeed: 0,
    distance: 0,
  };
}

export class AgentPathNavigator {
  constructor({
    maxSpeed = 3.5,
    minSpeed = 0,
    arriveRadius = 1.25,
    basis = DEFAULT_WORLD_BASIS
  }) {
    this.maxSpeed = maxSpeed;
    this.minSpeed = minSpeed;
    this.arriveRadius = arriveRadius;
    this.basis = basis;
    this.last = null;
  }

  reset() {
    this.last = null;
  }

  step({
    position = null,
    waypoint = null,
    movementEnabled = true,
    maxSpeed = this.maxSpeed,
  }) {

    if (movementEnabled === false || !position || !waypoint) {
      this.last = neutralIntent({ waypoint });
      return this.last;
    }

    const target = toVec3(waypoint);
    const toTarget = target.clone().sub(toVec3(position));
    this.basis.flatten(toTarget);

    const distance = toTarget.length();
    if (distance <= EPS) {
      this.last = neutralIntent({ waypoint: target });
      return this.last;
    }

    const speedLimit = Math.max(0, maxSpeed);
    const arrivalScale = this.arriveRadius > EPS
      ? clamp(distance / this.arriveRadius, 0, 1)
      : 1;
    const desiredSpeed = clamp(
      speedLimit * arrivalScale,
      Math.max(0, Math.min(this.minSpeed, speedLimit)),
      speedLimit
    );

    this.last = {
      waypoint: target.clone(),
      direction: toTarget.multiplyScalar(1 / distance),
      desiredSpeed,
      distance,
    };

    return this.last;
  }
}