class_name Mech extends Node3D @export_group("Skeleton") @export var _skeleton: Skeleton3D @export var _pelvis_attachment: BoneAttachment3D @export_subgroup("Left") @export var _ankle_bone_l: String = "Ankle_L" @export var _leg_ik_l: SkeletonIK3D @export var _leg_foot_body_l: CharacterBody3D @export var _leg_ik_target_l: Node3D @export var _leg_ik_magnet_l: Node3D @export_subgroup("Right") @export var _ankle_bone_r: String = "Ankle_R" @export var _leg_ik_r: SkeletonIK3D @export var _leg_foot_body_r: CharacterBody3D @export var _leg_ik_target_r: Node3D @export var _leg_ik_magnet_r: Node3D @export_group("Physics") @export var _foot_fall_acceleration: float = 1 @export_group("Walking") @export var _mouse_walk_sensitivity: float = 1 var _mouse_relative: Vector2 var _is_moving_leg_l: bool var _is_moving_leg_r: bool func _ready() -> void: _leg_ik_l.start() _leg_ik_r.start() _ready_leg_ik(_leg_foot_body_l, _ankle_bone_l) _ready_leg_ik(_leg_foot_body_r, _ankle_bone_r) func _process(_delta: float) -> void: _process_leg_ik(_leg_ik_l, _leg_ik_magnet_l) _process_leg_ik(_leg_ik_r, _leg_ik_magnet_r) _process_position() Debugger.text("_is_moving_leg_l", _is_moving_leg_l, 2) Debugger.text("_is_moving_leg_r", _is_moving_leg_r, 2) func _physics_process(_delta: float) -> void: if _is_moving_leg_l: _handle_leg_moving(_mouse_relative, _leg_foot_body_l) else: _handle_leg_physics(_leg_foot_body_l) if _is_moving_leg_r: _handle_leg_moving(_mouse_relative, _leg_foot_body_r) else: _handle_leg_physics(_leg_foot_body_r) _mouse_relative = Vector2.ZERO func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseMotion: var event_mouse := event as InputEventMouseMotion _mouse_relative = event_mouse.screen_relative else: _mouse_relative = Vector2.ZERO if event is InputEventMouseButton: var event_mouse := event as InputEventMouseButton if event_mouse.is_pressed(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED else: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if event_mouse.button_index == MOUSE_BUTTON_LEFT: _is_moving_leg_l = event_mouse.is_pressed() if event_mouse.button_index == MOUSE_BUTTON_RIGHT: _is_moving_leg_r = event_mouse.is_pressed() func _ready_leg_ik(foot_body: Node3D, bone: String) -> void: foot_body.position = ( _skeleton.get_bone_global_rest(_skeleton.find_bone(bone)).origin ) func _process_leg_ik(ik: SkeletonIK3D, ik_magnet: Node3D) -> void: ik.magnet = to_local(ik_magnet.global_position) func _process_position() -> void: var leg_target_pos_l := _leg_ik_target_l.global_position var leg_target_pos_r := _leg_ik_target_r.global_position var root_position := _pelvis_attachment.global_position root_position.y = minf(leg_target_pos_l.y, leg_target_pos_r.y) global_position = root_position func _handle_leg_moving(mouse_delta: Vector2, foot_body: CharacterBody3D) -> void: var velocity_local := Vector3( 0, -mouse_delta.y * _mouse_walk_sensitivity, mouse_delta.x * _mouse_walk_sensitivity ) foot_body.velocity = transform.basis * velocity_local foot_body.move_and_slide() foot_body.velocity = Vector3.ZERO func _handle_leg_physics(foot_body: CharacterBody3D) -> void: if foot_body.is_on_floor(): foot_body.velocity = Vector3.ZERO return foot_body.velocity.x = 0 foot_body.velocity.z = 0 foot_body.velocity.y -= _foot_fall_acceleration foot_body.move_and_slide()