Enhance climbing mechanics with detailed input and surface detection

This commit is contained in:
2026-04-30 00:33:13 +02:00
parent 2b7b1b61f3
commit c6091cb31c

View File

@@ -15,6 +15,8 @@ import {
CLIMB_INPUT_ACTIVE_THRESHOLD,
CLIMB_SPEED_METERS_PER_SECOND,
computeClimbPlaneMovement,
isClimbMovementIntoSurface,
resolveClimbPlanarInputDirection,
shouldEnterClimbing,
shouldExitClimbing,
type RuntimePlayerClimbSurface
@@ -425,7 +427,10 @@ export class FirstPersonNavigationController implements NavigationController {
this.publishTelemetry();
}
private resolveClimbProbeDirection(movementYawRadians: number): Vec3 {
private resolveClimbProbeDirection(
movementYawRadians: number,
inputState: ReturnType<typeof resolvePlayerStartActionInputs>
): Vec3 {
if (this.climbSurface !== null) {
return {
x: -this.climbSurface.normal.x,
@@ -434,6 +439,15 @@ export class FirstPersonNavigationController implements NavigationController {
};
}
const inputDirection = resolveClimbPlanarInputDirection(
inputState,
movementYawRadians
);
if (inputDirection.direction !== null) {
return inputDirection.direction;
}
return {
x: Math.sin(movementYawRadians),
y: 0,
@@ -491,22 +505,27 @@ export class FirstPersonNavigationController implements NavigationController {
const climbPressed = inputState.climb > CLIMB_INPUT_ACTIVE_THRESHOLD;
const jumpPressed = inputState.jump > CLIMB_INPUT_ACTIVE_THRESHOLD;
if (!climbPressed) {
this.climbLatchBlocked = false;
}
const climbSurface =
this.context.resolvePlayerClimbSurface?.(
this.feetPosition,
this.resolveClimbProbeDirection(movementYawRadians),
this.resolveClimbProbeDirection(movementYawRadians, inputState),
this.standingPlayerShape,
this.climbSurface
) ?? null;
const movementIntoSurface = isClimbMovementIntoSurface({
input: inputState,
movementYawRadians,
surface: climbSurface
});
const climbIntentActive = climbPressed || movementIntoSurface;
if (!climbIntentActive) {
this.climbLatchBlocked = false;
}
if (
this.climbSurface !== null &&
shouldExitClimbing({
climbInput: inputState.climb,
surface: climbSurface,
jumpPressed
})
@@ -572,10 +591,6 @@ export class FirstPersonNavigationController implements NavigationController {
return true;
}
if (climbSurface === null && climbPressed) {
this.climbLatchBlocked = true;
}
return false;
}
@@ -584,6 +599,7 @@ export class FirstPersonNavigationController implements NavigationController {
(this.climbLatchBlocked ||
!shouldEnterClimbing({
climbInput: inputState.climb,
movementIntoSurface,
surface: climbSurface,
jumpPressed
}))