diff --git a/Assets/Scripts/Player/PlayerAgent.cs b/Assets/Scripts/Player/PlayerAgent.cs index d1a75b2..36a7f87 100644 --- a/Assets/Scripts/Player/PlayerAgent.cs +++ b/Assets/Scripts/Player/PlayerAgent.cs @@ -37,8 +37,9 @@ namespace Projectiles [SerializeField] private float _cameraDistanceMin = 1.0f; [SerializeField] private float _cameraDistanceMax = 5.0f; [SerializeField] private Vector3 _shoulderOffset = new Vector3(0.4f, 1.6f, 0f); - [SerializeField] private LayerMask _cameraCollisionMask = ~0; // collide with world + [SerializeField] private LayerMask _cameraCollisionMask = ~0; // collide with world (exclude Player layer) [SerializeField] private float _cameraCollisionRadius = 0.15f; + [SerializeField] private float _cameraDistanceSmoothing = 10f; // smooth camera distance changes // --- Movement -------------------------------------------------------------- @@ -57,6 +58,9 @@ namespace Projectiles [SerializeField] private bool _faceMoveDirection = true; // if false, faces camera forward (aiming) [Networked] private Vector3 _moveVelocity { get; set; } + + // Smooth camera distance for collision response + private float _currentCameraDistance; // Local cache of most recent FUN (FixedUpdateNetwork) look to build on in Render/LateUpdate private Vector2 _lastFUNLookRotation; // (pitch,yaw) from KCC @@ -97,6 +101,9 @@ namespace Projectiles Weapons = GetComponent(); Health = GetComponent(); Input = GetComponent(); + + // Initialize camera distance + _currentCameraDistance = _cameraDistance; } private void LateUpdate() @@ -131,19 +138,23 @@ namespace Projectiles Vector3 dir = (desiredPos - pivotWorld); float len = dir.magnitude; Vector3 finalPos = desiredPos; + float targetDistance = _cameraDistance; if (len > 0.0001f) { dir /= len; if (Physics.SphereCast(pivotWorld, _cameraCollisionRadius, dir, out RaycastHit hit, len, _cameraCollisionMask, QueryTriggerInteraction.Ignore)) { - finalPos = pivotWorld + dir * Mathf.Max(hit.distance - 0.05f, _cameraDistanceMin); + targetDistance = Mathf.Max(hit.distance - 0.05f, _cameraDistanceMin); } } - // Clamp within min/max boom - float dist = Mathf.Clamp(Vector3.Distance(pivotWorld, finalPos), _cameraDistanceMin, _cameraDistanceMax); - finalPos = pivotWorld + dir * dist; + // Smooth the camera distance changes for less jarring collision response + _currentCameraDistance = Mathf.Lerp(_currentCameraDistance, targetDistance, _cameraDistanceSmoothing * Time.deltaTime); + + // Clamp within min/max boom and apply smoothed distance + _currentCameraDistance = Mathf.Clamp(_currentCameraDistance, _cameraDistanceMin, _cameraDistanceMax); + finalPos = pivotWorld + dir * _currentCameraDistance; cam.position = finalPos; cam.rotation = Quaternion.Euler(currentLook.x, currentLook.y, 0f); @@ -198,10 +209,12 @@ namespace Projectiles if (faceDir.sqrMagnitude > 0.0001f) { Quaternion target = Quaternion.LookRotation(faceDir, Vector3.up); - // FIXED: Use transform rotation instead of overriding look rotation - // This prevents interfering with camera pitch - Quaternion newRot = Quaternion.RotateTowards(transform.rotation, target, _turnSpeed * Runner.DeltaTime); - transform.rotation = newRot; + // Use KCC for body yaw rotation, but only set the Y (yaw) component + // This keeps the body rotation networked via KCC + Vector2 currentLook = KCC.GetLookRotation(); + float targetYaw = target.eulerAngles.y; + float newYaw = Mathf.MoveTowardsAngle(currentLook.y, targetYaw, _turnSpeed * Runner.DeltaTime); + KCC.SetLookRotation(new Vector2(currentLook.x, newYaw), _minPitch, _maxPitch); } // 5) Jump