Advanced Player Movement in Unity

In this tutorial, we'll explore advanced player movement mechanics in Unity, including sprinting, crouching, and a smooth camera system. These features add depth and polish to player controls, enhancing the overall gameplay experience. We will use Unity's physics system for realistic movement and interactions.

Setting Up the Scene

Before we dive into coding, let's set up a basic scene with a player object and a camera:

  1. Create a new Unity project.
  2. In the Hierarchy, create a 3D Cube, rename it to Player, and scale it to resemble a character (e.g., X: 1, Y: 2, Z: 1).
  3. Add a Rigidbody component to the Player and set the Interpolate property to Interpolate for smooth physics.
  4. Add a Capsule Collider component, adjust its height and radius to match the player model.
  5. Create an empty GameObject, name it CameraRig, and attach a Camera to it. Position the camera behind and slightly above the player.
  6. Make the CameraRig a child of the Player object to follow its movements.

Implementing Advanced Player Movement

We will implement a script that handles basic movement, sprinting, crouching, and smooth camera rotation.

PlayerMovement Script

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float walkSpeed = 5f;
    public float sprintSpeed = 10f;
    public float crouchSpeed = 2.5f;
    public float jumpForce = 5f;
    public float gravity = 20f;

    public Transform cameraTransform;
    public float lookSensitivity = 2f;
    public float maxLookAngle = 80f;

    private Rigidbody rb;
    private float currentSpeed;
    private bool isCrouching = false;
    private bool isGrounded = false;

    private void Start()
    {
        rb = GetComponent();
        rb.freezeRotation = true; // Prevent the Rigidbody from rotating
    }

    private void Update()
    {
        HandleMovement();
        HandleJumping();
        HandleCrouching();
        HandleCameraRotation();
    }

    private void HandleMovement()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 move = transform.right * moveHorizontal + transform.forward * moveVertical;
        move = move.normalized * currentSpeed * Time.deltaTime;

        Vector3 velocity = rb.velocity;
        velocity.x = move.x;
        velocity.z = move.z;
        rb.velocity = velocity;
    }

    private void HandleJumping()
    {
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
        }
    }

    private void HandleCrouching()
    {
        if (Input.GetKeyDown(KeyCode.LeftControl))
        {
            isCrouching = !isCrouching;
            currentSpeed = isCrouching ? crouchSpeed : walkSpeed;
            transform.localScale = new Vector3(1, isCrouching ? 0.5f : 1, 1);
        }

        if (Input.GetKey(KeyCode.LeftShift) && !isCrouching)
        {
            currentSpeed = sprintSpeed;
        }
        else if (!isCrouching)
        {
            currentSpeed = walkSpeed;
        }
    }

    private void HandleCameraRotation()
    {
        float mouseX = Input.GetAxis("Mouse X") * lookSensitivity;
        float mouseY = Input.GetAxis("Mouse Y") * lookSensitivity;

        Vector3 rotation = cameraTransform.localEulerAngles;
        rotation.y += mouseX;
        rotation.x -= mouseY;
        rotation.x = Mathf.Clamp(rotation.x, -maxLookAngle, maxLookAngle);

        cameraTransform.localEulerAngles = rotation;
    }

    private void OnCollisionStay(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = false;
        }
    }
}

Key Features and Explanation

Movement and Speed Control

The script uses Unity's Rigidbody to move the player, allowing for physics-based interactions. The speed varies based on whether the player is walking, sprinting, or crouching. Crouching is toggled with the LeftControl key, and sprinting occurs while holding the LeftShift key.

Jumping

The HandleJumping method applies an upward force when the player presses the jump button (default: space bar), given that the player is grounded. Ground detection is handled by checking for collisions with objects tagged "Ground".

Camera Control

The camera's rotation is controlled using the mouse, providing a first-person or third-person perspective based on the camera's positioning. The look angle is clamped to prevent excessive tilting, which can disorient players.

Conclusion

This tutorial provides a foundation for advanced player movement in Unity, covering various aspects like physics-based control, sprinting, crouching, and camera management. These techniques can be further customized and expanded to fit different game genres and styles, enhancing the player experience with responsive and realistic controls.

Remember, player movement is a critical aspect of gameplay and should be tuned carefully to ensure a satisfying player experience. Experiment with different values and features to find the best setup for your project.

Links
Unity