Posted June 20, 2024 by NC Studio
#horror #multiplayer #ik
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 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.
HandPositionController
script manages the hand's position relative to this target and any obstacles.
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); } }
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.
Mathf.SmoothStep
, creating a natural retracting motion.
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!