Fix grip handover with new movement component
This commit is contained in:
@ -23,9 +23,8 @@ var nearby_grips: Array[GripArea3D] = []
|
|||||||
@export var climb_speed: float = 2.0
|
@export var climb_speed: float = 2.0
|
||||||
@export var grip_handover_distance: float = 1 # How close to next grip to initiate handover
|
@export var grip_handover_distance: float = 1 # How close to next grip to initiate handover
|
||||||
@export var climb_acceleration: float = 10.0 # How quickly pawn reaches climb_speed
|
@export var climb_acceleration: float = 10.0 # How quickly pawn reaches climb_speed
|
||||||
@export var climb_angle_threshold_deg: float = 80.0 # How wide the forward cone is
|
@export var climb_angle_threshold_deg: float = 120.0 # How wide the forward cone is
|
||||||
@export var release_past_grip_threshold: float = 0.4 # How far past the grip origin before releasing
|
@export var release_past_grip_threshold: float = 0.4 # How far past the grip origin before releasing
|
||||||
var climb_direction_world: Vector3 = Vector3.ZERO # Direction currently climbing
|
|
||||||
var next_grip_target: GripArea3D = null # The grip we are trying to transition to
|
var next_grip_target: GripArea3D = null # The grip we are trying to transition to
|
||||||
|
|
||||||
# --- Launch Parameters ---
|
# --- Launch Parameters ---
|
||||||
@ -84,7 +83,7 @@ func process_movement(delta: float, move_input: Vector2, vertical_input: float,
|
|||||||
_process_reaching(delta)
|
_process_reaching(delta)
|
||||||
MovementState.GRIPPING:
|
MovementState.GRIPPING:
|
||||||
_apply_grip_physics(delta, move_input, roll_input)
|
_apply_grip_physics(delta, move_input, roll_input)
|
||||||
MovementState.CLIMBING:
|
MovementState.CLIMBING:
|
||||||
_apply_climb_physics(delta, move_input)
|
_apply_climb_physics(delta, move_input)
|
||||||
MovementState.CHARGING_LAUNCH:
|
MovementState.CHARGING_LAUNCH:
|
||||||
_handle_launch_charge(delta)
|
_handle_launch_charge(delta)
|
||||||
@ -99,7 +98,7 @@ func handle_collision(collision: KinematicCollision3D, collision_energy_loss: fl
|
|||||||
|
|
||||||
# === STATE MACHINE
|
# === STATE MACHINE
|
||||||
func _on_enter_state(state : MovementState):
|
func _on_enter_state(state : MovementState):
|
||||||
print("ZeroGMovementComponent activated for state: ", MovementState.keys()[state])
|
# print("ZeroGMovementComponent activated for state: ", MovementState.keys()[state])
|
||||||
if state == MovementState.GRIPPING:
|
if state == MovementState.GRIPPING:
|
||||||
pawn.velocity = Vector3.ZERO
|
pawn.velocity = Vector3.ZERO
|
||||||
pawn.angular_velocity = Vector3.ZERO
|
pawn.angular_velocity = Vector3.ZERO
|
||||||
@ -107,11 +106,11 @@ func _on_enter_state(state : MovementState):
|
|||||||
# state = MovementState.IDLE # Or SEARCHING?
|
# state = MovementState.IDLE # Or SEARCHING?
|
||||||
|
|
||||||
func _on_exit_state(state: MovementState):
|
func _on_exit_state(state: MovementState):
|
||||||
print("ZeroGMovementComponent deactivated for state: ", MovementState.keys()[state])
|
# print("ZeroGMovementComponent deactivated for state: ", MovementState.keys()[state])
|
||||||
|
|
||||||
# Ensure grip is released if pawn state changes unexpectedly
|
# Ensure grip is released if state changes unexpectedly
|
||||||
# if state == MovementState.GRIPPING:
|
if state == MovementState.GRIPPING:
|
||||||
# _release_current_grip()
|
_release_current_grip()
|
||||||
|
|
||||||
func _update_state(
|
func _update_state(
|
||||||
_delta: float,
|
_delta: float,
|
||||||
@ -221,33 +220,27 @@ func _apply_climb_physics(delta: float, move_input: Vector2):
|
|||||||
if not is_instance_valid(pawn) or not is_instance_valid(current_grip):
|
if not is_instance_valid(pawn) or not is_instance_valid(current_grip):
|
||||||
_stop_climb(true); return
|
_stop_climb(true); return
|
||||||
|
|
||||||
# 1. Calculate Climb Direction (same as _start_climb)
|
# 1. Calculate Climb Direction: For climbing we interpret W as up from the pawns perspective instead of forward
|
||||||
var pawn_forward = -pawn.global_transform.basis.z
|
var climb_direction = move_input.y * pawn.global_basis.y + move_input.x * pawn.global_basis.x
|
||||||
var pawn_right = pawn.global_transform.basis.x
|
climb_direction = climb_direction.normalized()
|
||||||
climb_direction_world = (pawn_forward * -move_input.y + pawn_right * move_input.x).normalized()
|
|
||||||
|
|
||||||
# 2. Find Next Grip
|
# 2. Find Next Grip
|
||||||
next_grip_target = _find_best_grip(climb_direction_world, INF, climb_angle_threshold_deg)
|
next_grip_target = _find_best_grip(climb_direction, INF, climb_angle_threshold_deg)
|
||||||
|
|
||||||
# 3. Check for Handover
|
# 3. Check for Handover: This should be more eager to mark a new grip as current than below check is to release when climbing past
|
||||||
var performed_handover = false
|
var performed_handover = _perform_grip_handover()
|
||||||
if is_instance_valid(next_grip_target):
|
|
||||||
var next_grip_pos = next_grip_target.global_position
|
|
||||||
var dist_sq_to_next = pawn.global_position.distance_squared_to(next_grip_pos)
|
|
||||||
if dist_sq_to_next < grip_handover_distance * grip_handover_distance:
|
|
||||||
performed_handover = _perform_grip_handover()
|
|
||||||
|
|
||||||
# 4. Check for Release Past Grip (if no handover)
|
# 4. Check for Release Past Grip (if no handover)
|
||||||
if not performed_handover:
|
if not performed_handover:
|
||||||
var current_grip_pos = current_grip.global_position
|
var current_grip_pos = current_grip.global_position
|
||||||
var vector_from_grip_to_pawn = pawn.global_position - current_grip_pos
|
var vector_from_grip_to_pawn = pawn.global_position - current_grip_pos
|
||||||
var distance_along_climb_dir = vector_from_grip_to_pawn.dot(climb_direction_world)
|
var distance_along_climb_dir = vector_from_grip_to_pawn.dot(climb_direction)
|
||||||
if distance_along_climb_dir > 0.2: # Release threshold
|
if distance_along_climb_dir > release_past_grip_threshold: # Release threshold
|
||||||
_release_current_grip()
|
_release_current_grip()
|
||||||
return # State changed to IDLE
|
return # State changed to IDLE
|
||||||
|
|
||||||
# 5. Apply Movement Force
|
# 5. Apply Movement Force
|
||||||
var target_velocity = climb_direction_world * climb_speed
|
var target_velocity = climb_direction * climb_speed
|
||||||
pawn.velocity = pawn.velocity.lerp(target_velocity, delta * climb_acceleration)
|
pawn.velocity = pawn.velocity.lerp(target_velocity, delta * climb_acceleration)
|
||||||
|
|
||||||
# 6. Apply Angular Force (Auto-Orient to current grip)
|
# 6. Apply Angular Force (Auto-Orient to current grip)
|
||||||
@ -341,7 +334,7 @@ func _find_best_grip(direction := Vector3.ZERO, max_distance_sq := INF, angle_th
|
|||||||
if angle_rad > max_allowed_angle_rad:
|
if angle_rad > max_allowed_angle_rad:
|
||||||
# print("Grip ", grip.get_parent().name, " outside cone. Angle: ", rad_to_deg(angle_rad), " > ", rad_to_deg(max_allowed_angle_rad))
|
# print("Grip ", grip.get_parent().name, " outside cone. Angle: ", rad_to_deg(angle_rad), " > ", rad_to_deg(max_allowed_angle_rad))
|
||||||
continue # Skip this grip if it's outside the cone
|
continue # Skip this grip if it's outside the cone
|
||||||
|
|
||||||
# If it passes all filters and is closer than the previous best:
|
# If it passes all filters and is closer than the previous best:
|
||||||
min_dist_sq = dist_sq
|
min_dist_sq = dist_sq
|
||||||
best_grip = grip
|
best_grip = grip
|
||||||
@ -382,17 +375,12 @@ func _start_climb(move_input: Vector2):
|
|||||||
var pawn_up = pawn.global_basis.y
|
var pawn_up = pawn.global_basis.y
|
||||||
var pawn_right = pawn.global_basis.x
|
var pawn_right = pawn.global_basis.x
|
||||||
|
|
||||||
# Project input onto plane perpendicular to grip normal? Or just use camera space?
|
print("ZeroGMoveController: Started Climbing in direction: ", (pawn_up * move_input.y + pawn_right * move_input.x).normalized())
|
||||||
# Let's use camera space initially for simplicity
|
|
||||||
climb_direction_world = (pawn_up * move_input.y + pawn_right * move_input.x).normalized()
|
|
||||||
|
|
||||||
print("ZeroGMoveController: Started Climbing in direction: ", climb_direction_world)
|
|
||||||
|
|
||||||
func _stop_climb(release_grip: bool):
|
func _stop_climb(release_grip: bool):
|
||||||
print("ZeroGMoveController: Stopping Climb. Release Grip: ", release_grip)
|
print("ZeroGMoveController: Stopping Climb. Release Grip: ", release_grip)
|
||||||
pawn.velocity = pawn.velocity.lerp(Vector3.ZERO, 0.5) # Apply some braking
|
pawn.velocity = pawn.velocity.lerp(Vector3.ZERO, 0.5) # Apply some braking
|
||||||
next_grip_target = null
|
next_grip_target = null
|
||||||
climb_direction_world = Vector3.ZERO
|
|
||||||
if release_grip:
|
if release_grip:
|
||||||
_release_current_grip() # Transitions to IDLE
|
_release_current_grip() # Transitions to IDLE
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user