// ClawCameraController.cs using UnityEngine; /// /// Keeps the camera's position and initial pitch/roll exactly as set in the Inspector. /// Rotates ONLY the yaw to track the target's yaw over time (no initial snap). /// public class ClawCameraController : MonoBehaviour { [Header("Target (use your claw root, e.g., craneA)")] public Transform target; [Header("Yaw Follow")] [Range(0f, 1f)] public float yawFollowFactor = 1f; // 1 = full follow public float yawOffsetDegrees = 0f; public float yawFollowSpeed = 10f; public float maxYawDegreesPerSecond = 0f; [Tooltip("Flip the follow direction if things feel reversed.")] public bool invertYaw = false; // Internals (captured at start to avoid snapping) private Transform _t; private float _camBasePitch; private float _camBaseYaw; private float _camBaseRoll; private float _targetBaseYaw; private float _yawVel; void Awake() { _t = transform; var e = _t.rotation.eulerAngles; _camBasePitch = e.x; _camBaseYaw = e.y; _camBaseRoll = e.z; if (!target) Debug.LogWarning("[ClawCameraController] No target set."); } void Start() { if (target) _targetBaseYaw = target.eulerAngles.y; } void LateUpdate() { if (!target) return; float targetYawNow = target.eulerAngles.y; float yawDelta = Mathf.DeltaAngle(_targetBaseYaw, targetYawNow); // (-180..180) float sign = invertYaw ? -1f : 1f; float desiredYaw = _camBaseYaw + (yawDelta * yawFollowFactor * sign) + yawOffsetDegrees; float currentYaw = _t.eulerAngles.y; float newYaw = Mathf.SmoothDampAngle(currentYaw, desiredYaw, ref _yawVel, 1f / Mathf.Max(0.0001f, yawFollowSpeed)); if (maxYawDegreesPerSecond > 0f) { float maxStep = maxYawDegreesPerSecond * Time.deltaTime; float step = Mathf.Clamp(Mathf.DeltaAngle(currentYaw, newYaw), -maxStep, maxStep); newYaw = currentYaw + step; } _t.rotation = Quaternion.Euler(_camBasePitch, newYaw, _camBaseRoll); } }