188 lines
5.4 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|