Implementing a Retracting Arm Mechanic with Final IK


Hi guys,

 In this devlog, I want to share a mechanic I developed for my latest project. It involves an arm that extends and retracts dynamically when it encounters obstacles. I achieved this using Final IK, specifically the ArmIK component. Let's dive into how it works, show some code snippets, and include a video demonstration.

The Mechanic

The concept is simple: the character's hand follows a reference point in front of the camera but retracts automatically when it detects an object in its path. To manage this, I used Final IK for the inverse kinematics (IK) solution.


In the video, you can see how the arm extends and retracts as it approaches and moves away from objects. This visual aid should help clarify how the script and the ArmIK component work together to achieve this effect.

How It Works

  1. Setup: The hand has an IK target that it tries to follow, positioned in front of the camera. The HandPositionController script manages the hand's position relative to this target and any obstacles.
  2. Obstacle Detection: The script uses a raycast to detect obstacles in front of the hand. If an obstacle is detected within a certain distance, the hand retracts smoothly.
  3. Movement Logic: The hand's movement is interpolated to create a smooth transition between extended and retracted positions. This ensures natural motion as the character navigates the environment.

Code Snippet

using Fusion;
using UnityEngine;
public class HandPositionController : NetworkBehaviour
{
    [SerializeField] private CameraManager cameraManager;
    [SerializeField] private Transform maxLimitTransform;
    [SerializeField] private Transform rightHandBone;
    [SerializeField] private float rayOffset = 90.0f; 
    [SerializeField] private float distance = 0.5f;
    private RaycastHit hit;
    private Vector3 handPosition;
    private int layerMask;
    private float t;
    private void Start()
    {
        layerMask = LayerMask.GetMask("Wall");
    }
    public void LateUpdate()
    {
        handPosition = UpdateHand();
        transform.localPosition = handPosition;
    }
    Vector3 UpdateHand()
    {
        Vector3 localHandPosition = transform.localPosition;
        Vector3 localMaxLimit = maxLimitTransform.localPosition;
        Vector3 direction = (Quaternion.Euler(0, rayOffset, 0) * rightHandBone.forward).normalized;
        if (Physics.Raycast(rightHandBone.position, direction.normalized, out hit, distance, layerMask)
            || IsPointInsideCollider(hit.collider, hit.point))
        {
            t = Mathf.Clamp01(hit.distance / distance);
            Vector3 newPosition = Vector3.Lerp(localMaxLimit, Vector3.zero, Mathf.SmoothStep(0f, 1f, t));
            return newPosition;
        }
        else
        {
            t = Mathf.Lerp(t, 1, Time.deltaTime * 2f);
            return Vector3.Lerp(localHandPosition, Vector3.zero, Mathf.SmoothStep(0f, 1f, t));
        }
    }
    bool IsPointInsideCollider(Collider collider, Vector3 point)
    {
        if (collider == null) return false;
        return collider.bounds.Contains(point);
    }
}


Using ArmIK

Final IK's ArmIK component is crucial for this mechanic. ArmIK allows precise control over the arm's movement and positioning. By setting the IK target to follow the reference point, and adjusting the hand position based on obstacle detection, we create a responsive and natural arm movement.

Key Features

  • Raycasting: A ray is cast from the hand to detect obstacles. If an obstacle is detected within the specified distance, the hand retracts.
  • Smooth Transition: The hand position transitions smoothly using Mathf.SmoothStep, creating a natural retracting motion.
  • Collision Check: Ensures the hand only retracts when it hits obstacles, maintaining a natural interaction with the environment.

Conclusion

This retracting arm mechanic adds a layer of interactivity and realism to the character's movements. Using Final IK  it was possible to achieve smooth and natural transitions. I hope this gives you some insights into implementing similar mechanics in your own projects!

Feel free to ask any questions or share your thoughts in the comments below. Happy developing!

Leave a comment

Log in with itch.io to leave a comment.