RiftMayhem/Assets/Scripts/CharacterCreation/CharacterLookatController.cs

55 lines
1.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterLookatController : MonoBehaviour
{
[SerializeField] private Transform headLookat;
[SerializeField] private Transform bodyLookat;
[SerializeField] private Transform headBone;
[Header("Head Rotation Limits")]
[SerializeField] private float maxYaw = 60f; // Left/right
[SerializeField] private float maxPitch = 30f; // Up/down
private void LateUpdate()
{
// Rotate body on XZ plane
Vector3 bodyLookatPlanarXZ = bodyLookat.position;
bodyLookatPlanarXZ.y = transform.position.y;
Vector3 bodyDirection = (bodyLookatPlanarXZ - transform.position).normalized;
if (bodyDirection != Vector3.zero)
transform.forward = bodyDirection;
// Head direction clamping
Vector3 headDirectionWorld = headLookat.position - headBone.position;
Quaternion lookRotation = Quaternion.LookRotation(headDirectionWorld, Vector3.up);
// Convert world rotation to local rotation relative to body
Quaternion localRotation = Quaternion.Inverse(transform.rotation) * lookRotation;
Vector3 localEuler = localRotation.eulerAngles;
// Convert angles from 0-360 to -180 to 180
localEuler.x = NormalizeAngle(localEuler.x);
localEuler.y = NormalizeAngle(localEuler.y);
// Clamp pitch (x) and yaw (y)
localEuler.x = Mathf.Clamp(localEuler.x, -maxPitch, maxPitch);
localEuler.y = Mathf.Clamp(localEuler.y, -maxYaw, maxYaw);
// Reconstruct the clamped rotation
Quaternion clampedLocalRotation = Quaternion.Euler(localEuler);
Quaternion clampedWorldRotation = transform.rotation * clampedLocalRotation;
headBone.rotation = clampedWorldRotation;
}
private float NormalizeAngle(float angle)
{
if (angle > 180f)
angle -= 360f;
return angle;
}
}