首页 / 模块目录 / 角色 / 载具运动 / HeadingRelativeCharacterMotionController

HeadingRelativeCharacterMotionController

three

把相对朝向的前后移动、左右横移、左右转向输入转成角色移动;推荐配 PoseFollowCameraRig。

类别角色 / 载具运动
依赖档位three
演示场character-sandbox · 角色沙盒 ↓
只取这个模块
modules/actor-motion/character/HeadingRelativeCharacterMotionController.js

连同其内部依赖一并复制,保留相对目录结构。

角色沙盒

three

自动巡逻——点击地面任意处让角色走过去。

源码

import { Vector3 } from 'three';
import { BaseCharacterMotionController } from './BaseCharacterMotionController.js';

export class HeadingRelativeCharacterMotionController extends BaseCharacterMotionController {
  constructor({
    turnRate = 2.8,
    ...config
  }) {
    super(config);
    this.cfg.turnRate = turnRate;
  }

  // forward/backward: 0..1 moves along the local forward/backward directions.
  // strafeLeft/strafeRight: 0..1 moves along the local left/right directions.
  // turnLeft/turnRight: 0..1 rotates toward the local left/right directions.
  planMovement({
    forward = 0,
    backward = 0,
    strafeLeft = 0,
    strafeRight = 0,
    turnLeft = 0,
    turnRight = 0,
    sprint = false,
    crouch = false,
    jump = false,
    deltaSeconds = 1 / 60,
    commit = false,
  }) {

    const moveRight = this.basis.controlSignal('left', strafeLeft) + this.basis.controlSignal('right', strafeRight);
    const moveForward = this.basis.controlSignal('backward', backward) + this.basis.controlSignal('forward', forward);
    const turnInput = this.basis.controlSignal('counterClockWise', turnLeft) + this.basis.controlSignal('clockWise', turnRight);
    const nextYaw = this.yaw + turnInput * this.cfg.turnRate * deltaSeconds;
    const inputLength = Math.hypot(moveRight, moveForward);
    const inputScale = inputLength > 1 ? 1 / inputLength : 1;
    const moveFrame = this.basis.yawPitchRollFrame(nextYaw);
    const moveDirection = inputLength > 0
      ? moveFrame.right
        .multiplyScalar(moveRight * inputScale)
        .addScaledVector(moveFrame.forward, moveForward * inputScale)
      : new Vector3();

    const intent = this._prepareLocomotion({
      moveDirection,
      sprint,
      crouch,
      jump,
      yaw: nextYaw,
      deltaSeconds,
    });

    if (commit) return this.commitMovement(intent);
    return intent;
  }
}