using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
float playerHeight = 2f;
[SerializeField] Transform orientation;
[Header("Movement")]
[SerializeField] float moveSpeed = 6f;
[SerializeField] float airMultiplier = 0.4f;
float movementMultiplier = 10f;
[Header("Sprinting")]
[SerializeField] float walkSpeed = 4f;
[SerializeField] float sprintSpeed = 6f;
[SerializeField] float acceleration = 10f;
[Header("Sprinting Effects")]
[SerializeField] Camera cam;
[SerializeField] float sprintFOV = 100f;
[Header("Jumping")]
public float jumpForce = 5f;
public float jumpRate = 15f;
[Header("Crouching")]
public float crouchScale = 0.75f;
public float crouchSpeed = 1f;
float crouchMultiplier = 5f;
[Header("Hover Settings")]
[SerializeField] float hoverHeight = 0.1f;
[SerializeField] float hoverActivationDistance = 0.5f;
public bool isHovering { get; private set; } = false;
[Header("Keybinds")]
[SerializeField] KeyCode jumpKey = KeyCode.Space;
[SerializeField] KeyCode sprintKey = KeyCode.LeftControl;
[SerializeField] KeyCode crouchKey = KeyCode.LeftShift;
[Header("Drag")]
[SerializeField] float groundDrag = 6f;
[SerializeField] float airDrag = 2f;
float horizontalMovement;
float verticalMovement;
[Header("Ground Detection")]
[SerializeField] Transform groundCheck;
[SerializeField] LayerMask groundMask;
[SerializeField] float groundDistance = 0.2f;
public bool isGrounded { get; private set; }
[SerializeField] BoxCollider hoverTriggerCollider;
[HideInInspector] public bool isCrouching;
[HideInInspector] public bool isSprinting;
[HideInInspector] public bool isMoving;
Vector3 moveDirection;
Rigidbody rb;
float nextTimeToJump = 0f;
private void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
if (hoverTriggerCollider == null)
{
hoverTriggerCollider = gameObject.AddComponent<BoxCollider>();
hoverTriggerCollider.isTrigger = true;
var mainCollider = GetComponent<BoxCollider>();
if (mainCollider != null)
{
hoverTriggerCollider.size = mainCollider.size * 1.1f;
hoverTriggerCollider.center = mainCollider.center;
}
}
}
private void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask) && !isHovering;
if (moveDirection == new Vector3(0f, 0f, 0f))
{
isMoving = false;
}
else
{
isMoving = true;
}
MyInput();
ControlDrag();
ControlSpeed();
if (Input.GetKey(jumpKey) && Time.time >= nextTimeToJump)
{
nextTimeToJump = Time.time + 1f / jumpRate;
Jump();
}
if (Input.GetKeyDown(crouchKey) && !isCrouching)
{
Crouch();
}
else if (Input.GetKeyUp(crouchKey) && isCrouching)
{
UnCrouch();
}
if (isSprinting && isMoving)
{
cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, sprintFOV, 8f * Time.deltaTime);
}
else if (!isSprinting && isMoving || !isSprinting && !isMoving)
{
cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, 90f, 8f * Time.deltaTime);
}
}
void MyInput()
{
horizontalMovement = Input.GetAxisRaw("Horizontal");
verticalMovement = Input.GetAxisRaw("Vertical");
moveDirection = orientation.forward * verticalMovement + orientation.right * horizontalMovement;
}
void Jump()
{
if (isGrounded)
{
rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
}
void Crouch()
{
Vector3 _crouchScale = new Vector3(transform.localScale.x, crouchScale, transform.localScale.z);
transform.localScale = _crouchScale;
isCrouching = true;
}
void UnCrouch()
{
Vector3 normalScale = new Vector3(transform.localScale.x, 0.9f, transform.localScale.z);
transform.localScale = normalScale;
isCrouching = false;
}
void ControlSpeed()
{
if (Input.GetKey(sprintKey) && isMoving)
{
moveSpeed = Mathf.Lerp(moveSpeed, sprintSpeed, acceleration * Time.deltaTime);
isSprinting = true;
}
else
{
moveSpeed = Mathf.Lerp(moveSpeed, walkSpeed, acceleration * Time.deltaTime);
isSprinting = false;
}
if (Input.GetKey(crouchKey))
{
moveSpeed = Mathf.Lerp(moveSpeed, crouchSpeed, acceleration * Time.deltaTime);
}
else
{
moveSpeed = Mathf.Lerp(moveSpeed, walkSpeed, acceleration * Time.deltaTime);
}
}
void ControlDrag()
{
if (isGrounded)
{
rb.linearDamping = groundDrag;
}
else
{
rb.linearDamping = airDrag;
}
}
private void FixedUpdate()
{
if (isHovering)
{
HoverEffect();
}
MovePlayer();
}
private void HoverEffect()
{
rb.useGravity = false;
rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z); // Фиксируем Y-скорость
RaycastHit hit;
if (Physics.Raycast(transform.position, Vector3.down, out hit, hoverActivationDistance + hoverHeight, groundMask))
{
float targetY = hit.point.y + hoverHeight;
transform.position = new Vector3(transform.position.x, targetY, transform.position.z);
}
}
void MovePlayer()
{
if (isGrounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * movementMultiplier, ForceMode.Acceleration);
}
else if (!isGrounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * movementMultiplier * airMultiplier, ForceMode.Acceleration);
}
else if (isCrouching)
{
rb.AddForce(moveDirection.normalized * moveSpeed * crouchMultiplier, ForceMode.Acceleration);
}
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Block"))
{
print("OnTriggerEnter");
rb.useGravity = false;
rb.linearVelocity = new Vector3(rb.linearVelocity.x, 0f, rb.linearVelocity.z); // Обнуляем вертикальную скорость
isHovering = true;
if (isSprinting)
{
cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, 90f, 8f * Time.deltaTime);
isSprinting = false;
}
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Block"))
{
isHovering = false;
rb.useGravity = true;
// Можно также сбросить вертикальную скорость, если нужно
// rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
}
}
}