Files
PIM_Laba3/Assets/Scripts/FPSController.cs
T
2026-05-25 23:10:02 +03:00

188 lines
5.4 KiB
C#

using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class FPSController : MonoBehaviour
{
[Header("References")]
public Camera playerCamera;
public Transform weaponHolder;
[Header("Movement")]
public float walkSpeed = 6f;
public float sprintSpeed = 8.5f;
public float jumpHeight = 1.2f;
public float gravity = -22f;
[Header("Look")]
public float mouseSensitivity = 260f;
public float maxLookAngle = 85f;
[Header("Recoil")]
public float recoilReturnSpeed = 12f;
public float recoilSnappiness = 18f;
[Header("Weapon Bob")]
public float bobFrequency = 9f;
public float bobHorizontalAmount = 0.018f;
public float bobVerticalAmount = 0.014f;
public float bobSmoothing = 10f;
private CharacterController _controller;
private Vector2 _lookAngles;
private Vector2 _recoilTarget;
private Vector2 _recoilCurrent;
private float _verticalVelocity;
private Vector3 _weaponHolderBaseLocalPosition;
private float _bobTime;
private bool _lookEnabled = true;
public void Initialize(Camera controlledCamera, Transform controlledWeaponHolder)
{
playerCamera = controlledCamera;
weaponHolder = controlledWeaponHolder;
}
private void Awake()
{
_controller = GetComponent<CharacterController>();
if (playerCamera == null)
{
playerCamera = GetComponentInChildren<Camera>(true);
}
if (weaponHolder == null && playerCamera != null)
{
Transform foundHolder = playerCamera.transform.Find("WeaponHolder");
if (foundHolder != null)
{
weaponHolder = foundHolder;
}
}
}
private void Start()
{
if (playerCamera != null)
{
_lookAngles.x = transform.eulerAngles.y;
_lookAngles.y = playerCamera.transform.localEulerAngles.x;
if (_lookAngles.y > 180f)
{
_lookAngles.y -= 360f;
}
}
if (weaponHolder != null)
{
_weaponHolderBaseLocalPosition = weaponHolder.localPosition;
}
SetCursorLocked(true);
}
private void Update()
{
if (!_lookEnabled || playerCamera == null)
{
return;
}
UpdateLook();
UpdateMovement();
UpdateWeaponBob();
}
public void SetLookEnabled(bool enabled)
{
_lookEnabled = enabled;
if (!enabled)
{
_recoilCurrent = Vector2.zero;
_recoilTarget = Vector2.zero;
}
}
public void SetCursorLocked(bool locked)
{
Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
Cursor.visible = !locked;
}
public void ApplyRecoil(float verticalKick, float horizontalKick)
{
_recoilTarget += new Vector2(verticalKick, Random.Range(-horizontalKick, horizontalKick));
}
private void UpdateLook()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
_lookAngles.x += mouseX;
_lookAngles.y = Mathf.Clamp(_lookAngles.y - mouseY, -maxLookAngle, maxLookAngle);
_recoilTarget = Vector2.Lerp(_recoilTarget, Vector2.zero, recoilReturnSpeed * Time.deltaTime);
_recoilCurrent = Vector2.Lerp(_recoilCurrent, _recoilTarget, recoilSnappiness * Time.deltaTime);
transform.rotation = Quaternion.Euler(0f, _lookAngles.x + _recoilCurrent.y, 0f);
playerCamera.transform.localRotation = Quaternion.Euler(_lookAngles.y - _recoilCurrent.x, 0f, 0f);
}
private void UpdateMovement()
{
Vector3 input = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
input = Vector3.ClampMagnitude(input, 1f);
float moveSpeed = Input.GetKey(KeyCode.LeftShift) ? sprintSpeed : walkSpeed;
Vector3 move = transform.TransformDirection(input) * moveSpeed;
if (_controller.isGrounded && _verticalVelocity < 0f)
{
_verticalVelocity = -2f;
}
if (_controller.isGrounded && Input.GetButtonDown("Jump"))
{
_verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
_verticalVelocity += gravity * Time.deltaTime;
move.y = _verticalVelocity;
_controller.Move(move * Time.deltaTime);
}
private void UpdateWeaponBob()
{
if (weaponHolder == null)
{
return;
}
Vector3 horizontalVelocity = _controller.velocity;
horizontalVelocity.y = 0f;
float speed = horizontalVelocity.magnitude;
if (_controller.isGrounded && speed > 0.15f)
{
_bobTime += Time.deltaTime * bobFrequency * (speed / walkSpeed);
Vector3 bobOffset = new Vector3(
Mathf.Cos(_bobTime * 0.5f) * bobHorizontalAmount,
Mathf.Sin(_bobTime) * bobVerticalAmount,
0f);
weaponHolder.localPosition = Vector3.Lerp(
weaponHolder.localPosition,
_weaponHolderBaseLocalPosition + bobOffset,
bobSmoothing * Time.deltaTime);
}
else
{
weaponHolder.localPosition = Vector3.Lerp(
weaponHolder.localPosition,
_weaponHolderBaseLocalPosition,
bobSmoothing * Time.deltaTime);
}
}
}