103 lines
3.5 KiB
C#
103 lines
3.5 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(CharacterController))]
|
|
public class FPSController : MonoBehaviour
|
|
{
|
|
public Camera playerCamera;
|
|
public float walkSpeed = 9f;
|
|
public float runSpeed = 18f;
|
|
public float jumpPower = 7f;
|
|
public float gravity = 20f;
|
|
public float lookSpeed = 2f;
|
|
public float lookXLimit = 45f;
|
|
public float airAcceleration = 2f;
|
|
public float groundFriction = 6f;
|
|
|
|
Vector3 velocity = Vector3.zero;
|
|
float rotationX = 0;
|
|
|
|
public bool canMove = true;
|
|
|
|
CharacterController characterController;
|
|
|
|
void Start()
|
|
{
|
|
characterController = GetComponent<CharacterController>();
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
Cursor.visible = false;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
Vector3 forward = playerCamera.transform.TransformDirection(Vector3.forward);
|
|
Vector3 right = playerCamera.transform.TransformDirection(Vector3.right);
|
|
forward.y = 0;
|
|
right.y = 0;
|
|
forward.Normalize();
|
|
right.Normalize();
|
|
|
|
bool isRunning = Input.GetKey(KeyCode.LeftShift);
|
|
float speed = isRunning ? runSpeed : walkSpeed;
|
|
Vector3 wishDir = forward * Input.GetAxis("Vertical") + right * Input.GetAxis("Horizontal");
|
|
|
|
if (characterController.isGrounded)
|
|
{
|
|
velocity.y = -0.5f; // Stick to the ground
|
|
|
|
if (canMove)
|
|
{
|
|
float drop = velocity.magnitude * groundFriction * Time.deltaTime;
|
|
velocity *= Mathf.Max(velocity.magnitude - drop, 0) / velocity.magnitude; // Apply friction
|
|
|
|
Accelerate(wishDir, speed, groundFriction); // Ground accelerate
|
|
|
|
if (Input.GetButton("Jump"))
|
|
{
|
|
velocity.y = jumpPower; // Jump
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
velocity.y -= gravity * Time.deltaTime; // Apply gravity
|
|
|
|
if (canMove)
|
|
{
|
|
// Air acceleration is now dependant on how aligned the move direction is with the current velocity direction
|
|
// The closer to straight ahead, the more acceleration, allowing for more maneuverability while keeping strafe speed under control
|
|
float currentSpeed = Vector3.Dot(velocity, wishDir);
|
|
float accel = airAcceleration * Mathf.Max(0, 1 - currentSpeed / speed);
|
|
Accelerate(wishDir, speed, accel);
|
|
}
|
|
}
|
|
|
|
// Apply movement
|
|
characterController.Move(velocity * Time.deltaTime);
|
|
|
|
// Looking
|
|
if (canMove)
|
|
{
|
|
rotationX += -Input.GetAxis("Mouse Y") * lookSpeed;
|
|
rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
|
|
playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
|
|
transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0);
|
|
}
|
|
}
|
|
|
|
// Acceleration function to add force to the velocity in the given direction
|
|
void Accelerate(Vector3 wishDir, float wishSpeed, float accel)
|
|
{
|
|
float currentSpeed = Vector3.Dot(velocity, wishDir);
|
|
float addSpeed = wishSpeed - currentSpeed;
|
|
if (addSpeed <= 0) return;
|
|
float accelerationSpeed = accel * Time.deltaTime * wishSpeed;
|
|
if (accelerationSpeed > addSpeed)
|
|
{
|
|
accelerationSpeed = addSpeed;
|
|
}
|
|
velocity += wishDir.normalized * accelerationSpeed;
|
|
}
|
|
}
|