Improve third-person climbing logic and planar movement detection
This commit is contained in:
@@ -15,6 +15,8 @@ import {
|
|||||||
CLIMB_INPUT_ACTIVE_THRESHOLD,
|
CLIMB_INPUT_ACTIVE_THRESHOLD,
|
||||||
CLIMB_SPEED_METERS_PER_SECOND,
|
CLIMB_SPEED_METERS_PER_SECOND,
|
||||||
computeClimbPlaneMovement,
|
computeClimbPlaneMovement,
|
||||||
|
isClimbMovementIntoSurface,
|
||||||
|
resolveClimbPlanarInputDirection,
|
||||||
shouldEnterClimbing,
|
shouldEnterClimbing,
|
||||||
shouldExitClimbing,
|
shouldExitClimbing,
|
||||||
type RuntimePlayerClimbSurface
|
type RuntimePlayerClimbSurface
|
||||||
@@ -665,7 +667,10 @@ export class ThirdPersonNavigationController implements NavigationController {
|
|||||||
this.publishTelemetry();
|
this.publishTelemetry();
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveClimbProbeDirection(movementYawRadians: number): Vec3 {
|
private resolveClimbProbeDirection(
|
||||||
|
movementYawRadians: number,
|
||||||
|
inputState: ReturnType<typeof resolvePlayerStartActionInputs>
|
||||||
|
): Vec3 {
|
||||||
if (this.climbSurface !== null) {
|
if (this.climbSurface !== null) {
|
||||||
return {
|
return {
|
||||||
x: -this.climbSurface.normal.x,
|
x: -this.climbSurface.normal.x,
|
||||||
@@ -674,6 +679,15 @@ export class ThirdPersonNavigationController implements NavigationController {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const inputDirection = resolveClimbPlanarInputDirection(
|
||||||
|
inputState,
|
||||||
|
movementYawRadians
|
||||||
|
);
|
||||||
|
|
||||||
|
if (inputDirection.direction !== null) {
|
||||||
|
return inputDirection.direction;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: Math.sin(movementYawRadians),
|
x: Math.sin(movementYawRadians),
|
||||||
y: 0,
|
y: 0,
|
||||||
@@ -731,22 +745,27 @@ export class ThirdPersonNavigationController implements NavigationController {
|
|||||||
const climbPressed = inputState.climb > CLIMB_INPUT_ACTIVE_THRESHOLD;
|
const climbPressed = inputState.climb > CLIMB_INPUT_ACTIVE_THRESHOLD;
|
||||||
const jumpPressed = inputState.jump > CLIMB_INPUT_ACTIVE_THRESHOLD;
|
const jumpPressed = inputState.jump > CLIMB_INPUT_ACTIVE_THRESHOLD;
|
||||||
|
|
||||||
if (!climbPressed) {
|
|
||||||
this.climbLatchBlocked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const climbSurface =
|
const climbSurface =
|
||||||
this.context.resolvePlayerClimbSurface?.(
|
this.context.resolvePlayerClimbSurface?.(
|
||||||
this.feetPosition,
|
this.feetPosition,
|
||||||
this.resolveClimbProbeDirection(movementYawRadians),
|
this.resolveClimbProbeDirection(movementYawRadians, inputState),
|
||||||
this.standingPlayerShape,
|
this.standingPlayerShape,
|
||||||
this.climbSurface
|
this.climbSurface
|
||||||
) ?? null;
|
) ?? null;
|
||||||
|
const movementIntoSurface = isClimbMovementIntoSurface({
|
||||||
|
input: inputState,
|
||||||
|
movementYawRadians,
|
||||||
|
surface: climbSurface
|
||||||
|
});
|
||||||
|
const climbIntentActive = climbPressed || movementIntoSurface;
|
||||||
|
|
||||||
|
if (!climbIntentActive) {
|
||||||
|
this.climbLatchBlocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.climbSurface !== null &&
|
this.climbSurface !== null &&
|
||||||
shouldExitClimbing({
|
shouldExitClimbing({
|
||||||
climbInput: inputState.climb,
|
|
||||||
surface: climbSurface,
|
surface: climbSurface,
|
||||||
jumpPressed
|
jumpPressed
|
||||||
})
|
})
|
||||||
@@ -812,10 +831,6 @@ export class ThirdPersonNavigationController implements NavigationController {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (climbSurface === null && climbPressed) {
|
|
||||||
this.climbLatchBlocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,6 +839,7 @@ export class ThirdPersonNavigationController implements NavigationController {
|
|||||||
(this.climbLatchBlocked ||
|
(this.climbLatchBlocked ||
|
||||||
!shouldEnterClimbing({
|
!shouldEnterClimbing({
|
||||||
climbInput: inputState.climb,
|
climbInput: inputState.climb,
|
||||||
|
movementIntoSurface,
|
||||||
surface: climbSurface,
|
surface: climbSurface,
|
||||||
jumpPressed
|
jumpPressed
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ describe("player climbing helpers", () => {
|
|||||||
isClimbMovementIntoSurface({
|
isClimbMovementIntoSurface({
|
||||||
input: createInputState({ moveForward: 1 }),
|
input: createInputState({ moveForward: 1 }),
|
||||||
movementYawRadians: 0,
|
movementYawRadians: 0,
|
||||||
surface,
|
surface
|
||||||
})
|
})
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
Reference in New Issue
Block a user