137 lines
5.0 KiB
C#
137 lines
5.0 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()
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
} |