@ferret/character
Character movement (capsule, walk, run, jump, steps, slopes), cameras and the player controller.
Classes
CameraRig class
class CameraRigThe player's camera: first or third person, switchable at run time. The third-person boom is a spring arm: it is shortened when a wall is in the way, so the camera never clips into the level. Inputs of Babylon's own are removed.
readonly camera: BABYLON.FreeCamera | |
view: ViewMode | |
yaw: number | |
pitch: number | |
distance: number | |
currentDistance: number | the boom length actually used after collision |
readonly o: Required<Omit<CameraRigOptions, 'mask'>> & { mask: number } | |
boom: ExternalBoom | null | a boom fixed on something else than the character (a ride); update uses it in place of the first/third person camera while it is set |
constructor(scene: BABYLON.Scene, private physics: PhysicsService, opts: CameraRigOptions = {}) | |
toggleView() | |
setView(v: ViewMode) | |
zoom(delta: number) | |
look(dyaw: number, dpitch: number) | |
groundForward(out = new BABYLON.Vector3()) | Forward on the ground plane for the current yaw (what "move forward" means). |
groundRight(out = new BABYLON.Vector3()) | |
setBoom(b: ExternalBoom | null) | Fix the camera on a boom of its own (or back on the character with null). |
blendFromCurrent(duration: number, exp = 2) | Start a timed blend from where the camera is now to wherever update puts it (UE: SetViewTargetWithBlend, ease in-out). |
get blending() | |
update(feet: BABYLON.Vector3, dt: number) | Place the camera for a rendered frame; feet is the interpolated position of the character. |
packages/character/src/camera.ts:45
CharacterMovement class
class CharacterMovement extends Component<CharacterParams>Capsule character movement against static geometry: walk, run, crouch, jump, step up, slopes, ground snapping, moving platforms. The same component moves the player and NPCs; they differ only in who sets the move input. The entity's node must be a Babylon Mesh (it carries the collision ellipsoid); its origin is at the feet.
p: Required<Omit<CharacterParams, 'groundMask'>> & { groundMask?: string[] } | |
velocity: Vector3 | |
grounded: boolean | |
groundNormal: Vector3 | |
groundMesh: BABYLON.AbstractMesh | null | |
crouching: boolean | |
running: boolean | |
submerged: number | 0..1: the part of the body inside water or mud (capability D); swimming when most of it is and the feet are off the ground |
swimming: boolean | |
yaw: number | |
flying: boolean | flying (UE: MOVE_Flying): no gravity, no ground; the vertical speed follows setVerticalInput times verticalSpeed; the horizontal speed is walk/run speed as on the ground |
verticalSpeed: number | m/s at full vertical input in flying mode |
prevPosition: Vector3 | where the body was at the previous fixed step (camera interpolation) |
get mesh(): BABYLON.Mesh | |
get height() | |
get speed2d() | |
onAttach() | |
onDetach() | |
setMoveInput(dir: BABYLON.Vector3, run = false) | Desired movement in world space; its length (0..1) scales the speed. The vertical part is used only while swimming: Unreal swims along the view direction, pitch included. |
jump() | |
setVerticalInput(v: number) | Flying mode: -1..1, up positive. |
setFlying(on: boolean) | Switch flying mode on or off (off: the character falls and lands by the normal rules). |
motionState() | what an Animator needs to know (see MotionSource in |
setCrouch(on: boolean) | |
shift(d: BABYLON.Vector3): BABYLON.Vector3 | Move the capsule horizontally by d now, with collisions and step-ups, outside the velocity model (room-scale VR: the player walked in the room). Returns the distance actually moved. |
teleport(pos: BABYLON.Vector3) | |
onFixedUpdate(dt: number) | |
renderPosition(alpha: number, out = new BABYLON.Vector3()) | The interpolated position for the render frame (the camera follows this). |
packages/character/src/movement.ts:70
PlayerController class
class PlayerController extends Component<PlayerParams>The player controller: input actions -> movement and camera. First and third person; the third-person body faces where it moves, the first-person body faces where the camera looks.
viewOverride: ViewOverride | null | Another owner of the view (a VR headset: the head owns the camera). While it is set, the controller does not move or aim the camera rig, look / turn are left to the owner, and "forward" is yaw(). |
rig: CameraRig | |
movement: CharacterMovement | |
onAttach() | |
get view(): ViewMode | |
setView(v: ViewMode) | |
toggleView() | |
onFixedUpdate(dt: number) | |
onUpdate(dt: number) | |
onDetach() |
packages/character/src/player.ts:41
Functions
easeInOut function
function easeInOut(a: number, exp = 2): numberUE's FMath::InterpEaseInOut(0, 1, a, exp): slow at both ends.
packages/character/src/camera.ts:6
spawnCharacter function
function spawnCharacter(world: World, name: string, position: BABYLON.Vector3, params: CharacterParams & { layer?: string } = {}): { entity: Entity; movement: CharacterMovement; mesh: BABYLON.Mesh }A character entity: an invisible Mesh with the collision ellipsoid, a Collider on the Pawn layer and CharacterMovement.
packages/character/src/movement.ts:433
Interfaces
CameraRigOptions interface
interface CameraRigOptionsview?: ViewMode | |
eyeHeight?: number | metres above the feet where the eyes are (first person) and the boom pivots (third person) |
distance?: number | third person: distance behind the pivot, and its limits for zoom |
minDistance?: number | |
maxDistance?: number | |
shoulder?: number | third person: sideways offset of the pivot (over the shoulder) |
pitchMin?: number | |
pitchMax?: number | |
probe?: number | third person: radius kept free between the camera and the walls |
mask?: number | layers the spring arm collides with |
packages/character/src/camera.ts:23
CharacterParams interface
interface CharacterParamsParameters follow UE's Character Movement Component, in metres and seconds.
radius?: number | |
height?: number | |
crouchHeight?: number | |
eyeHeight?: number | |
walkSpeed?: number | |
runSpeed?: number | |
crouchSpeed?: number | |
jumpVelocity?: number | initial vertical speed of a jump (UE: JumpZVelocity) |
gravity?: number | |
mass?: number | kg: how much push a character has against water or mud (capability D), with thrust |
bodyDensity?: number | kg/m³: below the density of the water it floats, above it sinks (people are about 985) |
thrust?: number | m/s²: the push the character can make against drag in a medium (swimming, wading); the speed it reaches there follows from it |
swimSpeed?: number | m/s: UE MaxSwimSpeed. Set, a character in a dense medium (swimming) moves at exactly this speed whatever the walk, run or crouch state, as Unreal's swimming mode does; unset, the speed follows from thrust and the drag |
buoyancy?: number | UE Buoyancy: 1 = neutral (the weight is carried completely in the medium), below 1 sinks, above 1 rises. Unset: the density ratio medium / bodyDensity decides |
outOfWaterZ?: number | UE OutofWaterZ, m/s: the upward speed of the water jump (swimming against a ledge, the input pointing up) |
jumpOutOfWaterPitch?: number | UE JumpOutOfWaterPitch, degrees: the water jump needs the swim input to point at least this far above the horizon |
maxOutOfWaterStepHeight?: number | UE MaxOutOfWaterStepHeight, m: how far above the body's centre the ledge may be for a water jump |
swimAcceleration?: number | m/s²: UE MaxAcceleration while swimming (the push along the 3D swim input) |
fluidFriction?: number | UE PhysicsVolume FluidFriction (0.3 by default) of the water; with BrakingDecelerationSwimming 0 a stopped swimmer coasts by it times BrakingFrictionFactor 2 |
maxWindAccel?: number | m/s²: the most the wind (the flow service) can push the character; 0 turns the wind off for it (a game's cap) |
maxStepHeight?: number | |
walkableAngle?: number | steepest slope that can be walked, degrees (UE: WalkableFloorAngle) |
acceleration?: number | |
braking?: number | |
airControl?: number | fraction of the ground acceleration available in the air |
snapDistance?: number | how far below the feet the ground is still "ground" when walking down |
groundMask?: string[] | layer names the character collides with when probing the ground |
faceMovement?: boolean | turn the body to face where it moves (third person); first person sets the yaw from the camera |
turnRate?: number | |
flyAcceleration?: number | flying mode: m/s²: how fast the vertical speed follows setVerticalInput |
packages/character/src/movement.ts:5
ExternalBoom interface
interface ExternalBoomA boom on a point of the game's own (a mount's seat): UE's spring arm with camera lag and an absolute rotation.
pivot: () => BABYLON.Vector3 | where the boom is fixed, world space, metres (read every frame) |
arm: number | boom length, metres |
socketZ?: number | lift of the camera above the boom's end (UE: SocketOffset.Z), metres |
lag?: number | camera lag speed (UE: CameraLagSpeed); 0 = no lag |
packages/character/src/camera.ts:12
PlayerActions interface
interface PlayerActionsThe names of the game's actions that the controller reads. Anything left out is simply not used.
move?: string | |
look?: string | |
turn?: string | |
jump?: string | |
run?: string | |
crouch?: string | |
view?: string | |
zoom?: string |
packages/character/src/player.ts:8
PlayerParams interface
interface PlayerParamsactions?: PlayerActions | |
camera?: CameraRigOptions | |
turnSpeed?: number | rad/s at full turn |
alwaysRun?: boolean | a console has no run button: run when the stick is fully pushed, or always |
bodyInFirstPerson?: boolean | first person: show the body (arms/legs) |
body?: BABYLON.AbstractMesh[] | meshes that make up the visible body; hidden in first person unless bodyInFirstPerson |
packages/character/src/player.ts:19
ViewOverride interface
interface ViewOverrideyaw(): number | the yaw "move forward" follows, radians |
packages/character/src/player.ts:32
Types
ViewMode type
type ViewMode = 'first' | 'third'packages/character/src/camera.ts:3