Souljack/Assets/_Project/Scripts/PlayerUtils/PlayerCamera.cs

138 lines
5.1 KiB
C#

using UnityEngine;
namespace _Project.Scripts.PlayerUtils
{
public class PlayerCamera : MonoBehaviour
{
[Header("Камера и Настройки")]
[SerializeField] private Transform cameraPosition;
[SerializeField] private float mouseSensitivity = 0.1f;
[SerializeField] private float maxLookAngle = 80f;
[Header("Высота камеры")]
[SerializeField] private float standingCameraY = 1.6f;
[SerializeField] private float crouchingCameraY = 0.8f;
[SerializeField] private float crouchTransitionSpeed = 15f;
[SerializeField] private float slideCameraTiltAngle = 4f;
[Header("Тряска Камеры (Headbob)")]
public bool enableHeadBob = true;
[SerializeField] private float walkBobSpeed = 12f;
[SerializeField] private float walkBobAmount = 0.04f;
[SerializeField] private float sprintBobSpeed = 15f;
[SerializeField] private float sprintBobAmount = 0.07f;
[SerializeField] private float impactRecoverySpeed = 6f;
public Transform CameraTransform => cameraPosition;
private PlayerControls controls;
private PlayerMovement movement;
private float cameraPitch = 0f;
private float yRotation = 0f;
private float currentCameraTilt = 0f;
private float baseCameraY;
private float bobTimer = 0f;
private Vector3 bobOffset = Vector3.zero;
private float currentImpactOffset = 0f;
private bool stepTaken = false;
private void Start()
{
controls = Player.Instance.Controls;
movement = Player.Instance.Movement;
mouseSensitivity = PlayerPrefs.GetFloat("MouseSensitivity", mouseSensitivity);
baseCameraY = standingCameraY;
yRotation = transform.eulerAngles.y;
}
public void ApplyProfile(BodyProfile profile)
{
standingCameraY = profile.standingCameraY;
crouchingCameraY = profile.crouchingCameraY;
walkBobSpeed = profile.walkBobSpeed;
sprintBobSpeed = profile.walkBobSpeed * 1.25f;
walkBobAmount = profile.walkBobAmount;
sprintBobAmount = profile.walkBobAmount * 1.6f;
slideCameraTiltAngle = profile.slideTiltAngle;
}
public void SetYaw(float yaw)
{
yRotation = yaw;
transform.rotation = Quaternion.Euler(0f, yRotation, 0f);
}
private void Update()
{
if (Time.timeScale == 0f) return;
HandleMouseLook();
HandleCameraAndBobbing();
}
private void HandleMouseLook()
{
Vector2 lookInput = controls.Player.Look.ReadValue<Vector2>();
float dt = Time.unscaledDeltaTime;
cameraPitch -= lookInput.y * mouseSensitivity;
cameraPitch = Mathf.Clamp(cameraPitch, -maxLookAngle, maxLookAngle);
float targetTilt = movement.IsSliding ? -slideCameraTiltAngle : 0f;
currentCameraTilt = Mathf.Lerp(currentCameraTilt, targetTilt, dt * 10f);
cameraPosition.localRotation = Quaternion.Euler(cameraPitch, 0f, currentCameraTilt);
yRotation += lookInput.x * mouseSensitivity;
transform.rotation = Quaternion.Euler(0f, yRotation, 0f);
}
private void HandleCameraAndBobbing()
{
float dt = Time.unscaledDeltaTime;
bool isLowered = movement.IsCrouching || movement.IsSliding;
float targetCamY = isLowered ? crouchingCameraY : standingCameraY;
baseCameraY = Mathf.Lerp(baseCameraY, targetCamY, dt * crouchTransitionSpeed);
bool isMoving = movement.MoveInput.sqrMagnitude > 0.01f && movement.IsGrounded && !movement.IsSliding;
if (isMoving && enableHeadBob)
{
float speed = movement.IsSprinting ? sprintBobSpeed : walkBobSpeed;
float amount = movement.IsSprinting ? sprintBobAmount : walkBobAmount;
bobTimer += dt * speed;
bobOffset.x = Mathf.Cos(bobTimer * 0.5f) * amount;
bobOffset.y = Mathf.Sin(bobTimer) * amount;
if (Mathf.Sin(bobTimer) <= -0.9f && !stepTaken)
{
Player.Instance.Sound.PlayFootstep(movement.IsSprinting);
stepTaken = true;
}
else if (Mathf.Sin(bobTimer) > -0.2f) stepTaken = false;
}
else
{
bobTimer = 0f;
stepTaken = false;
bobOffset = Vector3.Lerp(bobOffset, Vector3.zero, dt * 10f);
}
currentImpactOffset = Mathf.Lerp(currentImpactOffset, 0f, dt * impactRecoverySpeed);
cameraPosition.localPosition = new Vector3(bobOffset.x, baseCameraY + bobOffset.y - currentImpactOffset, 0f);
}
public void ApplyRecoil(float amount)
{
cameraPitch -= amount;
}
public void TriggerJumpImpact()
{
if (enableHeadBob) currentImpactOffset = 0.1f;
}
}
}