Implement the player controls for an ER game

Player controls are the backbone of any game, and when it comes to crafting an endless runner (ER) game, they play a pivotal role in delivering an engaging and thrilling experience. By allowing players to seamlessly navigate their character through the ever-unfolding challenges, we empower them to overcome obstacles, collect rewards, and immerse themselves in the action. Let’s dive into implementing the essential player controls for our ER game.

Implement continuous forward movement

In an ER game, the player’s character moves forward automatically, creating a sense of urgency and excitement. To achieve this, we script our player character to move along its forward axis at a consistent speed. We can use Unity’s Rigidbody component to ensure smooth movement and physics interactions.

Attach the following script with the player:

using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5.0f;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
// Implement the continuous forward movement
Vector3 forwardMovement = transform.forward * moveSpeed * Time.deltaTime;
rb.MovePosition(transform.position + forwardMovement);
}
}

The C# script above defines a PlayerController class that handles basic player movement:

  • Line 1: Namespace declaration for the UnityEngine, which is the core namespace for Unity game development.

  • Line 3: The PlayerController class inherits from MonoBehaviour, which is the base class from Unity for all scripts.

  • Lines 5–6: A public float moveSpeed is initialized to 5.0 for player speed, and a private Rigidbody rb is declared for physics control.

  • Lines 8–11: The Start method, which is called on the frame when the script is enabled, initializes the rb variable by getting the Rigidbody component attached to the same GameObject.

  • Lines 13–18: The Update method is called once per frame and it’s where the player’s movement is handled. Inside, a Vector3 variable forwardMovement is created to represent the player’s forward direction, multiplied by the move speed and the time passed since the last frame (Time.deltaTime), ensuring smooth movement. The player’s position is updated by using the Rigidbody.MovePosition function.

Sideways navigation

Unlike linear platformers, ER games often offer the ability to move sideways. Implement this control by detecting input from the player’s preferred keys or touch gestures. For keyboard controls, use Unity’s input system to capture arrow key presses. For mobile devices, handle touch input to determine the desired lateral movement.

using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5.0f;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
// Implement side-to-side movement using the right and left arrow buttons
float horizontalInput = Input.GetAxis("Horizontal");
Vector3 movement = new Vector3(horizontalInput, 0, 0) * moveSpeed * Time.deltaTime;
// Implement continuous forward movement
Vector3 forwardMovement = transform.forward * moveSpeed * Time.deltaTime;
rb.MovePosition(transform.position + forwardMovement + movement);
}
}

The code sets up a basic player movement in a Unity game:

  • Lines 5–6: Public variable moveSpeed is set to 5.0 for the player's speed. rb is a private Rigidbody for physics interactions.

  • Line 8–11: In the Start method, rb gets the Rigidbody component attached to this game object.

  • Lines 15–17: In the Update method, horizontal input from the player (using arrow keys) is retrieved and used to create a movement vector.

  • Lines 19–21: A forwardMovement vector is defined for continuous forward motion. rb.MovePosition combines the current position with the forward and horizontal movement vectors to move the player.

Jumping mechanism

Adding a jumping mechanism introduces an extra layer of dynamism to our ER game. Allow the player character to jump over obstacles or gaps by detecting a specific input command. Implement a jump script that utilizes Unity's Rigidbody to apply an upward force, simulating a jump motion.

using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5.0f;
public float jumpForce = 10.0f;
public LayerMask groundLayer;
private Rigidbody rb;
private bool isGrounded;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
isGrounded = Physics.Raycast(transform.position, Vector3.down, 0.5f, groundLayer);
// Implement side-to-side movement using the right and left arrow buttons
float horizontalInput = Input.GetAxis("Horizontal");
Vector3 movement = new Vector3(horizontalInput, 0, 0) * moveSpeed * Time.deltaTime;
// Implement continuous forward movement
Vector3 forwardMovement = transform.forward * moveSpeed * Time.deltaTime;
rb.MovePosition(transform.position + forwardMovement + movement);
if (isGrounded && Input.GetAxis("Vertical") > 0)
{
rb.velocity = new Vector3(rb.velocity.x, CalculateJumpVelocity(), rb.velocity.z);
}
}
private float CalculateJumpVelocity()
{
// Calculate the jump velocity based on desired jump height and gravity
float jumpVelocity = Mathf.Sqrt(jumpForce * Mathf.Abs(Physics.gravity.y));
return jumpVelocity;
}
}

The script above is a Unity C# script for a player controller with basic movement and jumping mechanics.

  • Lines 3: Declares the PlayerController class, derived from MonoBehaviour, to enable script attachment to a GameObject.

  • Lines 5–7: Public variables moveSpeed, jumpForce, and groundLayer are set, dictating the player's speed, jumping mechanics, and ground detection layer, respectively.

  • Lines 10: Private variables rb (Rigidbody) and isGrounded (boolean) are declared for physics control and ground state checking.

  • Lines 12–15: The Start method assigns the GameObject's Rigidbody to rb. It's called at game start.

  • Lines 16–34: The Update method checks if the player is grounded with Physics.Raycast, collects horizontal input for side movement, constructs a lateral movement vector from this input scaled by move speed and frame time, defines a forward movement vector, updates the Rigidbody's position with these movements, and, if grounded with jump input detected, applies a jump force.

  • Lines 36–41: Define a private method CalculateJumpVelocity, which computes the velocity needed to achieve the desired jump force considering gravity.

We also want our camera to move with the player. We can attach the following script with the camera GameObject and drag/drop the player GameObject into the placeholder.

using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target; // Reference to the player's transform
public Vector3 offset = new Vector3(0, 5, -10); // Offset from the player's position
private void Update()
{
if (target == null)
return;
// Calculate the desired camera position based on the player's position and offset
Vector3 desiredPosition = target.position + offset;
// Smoothly move the camera towards the desired position
transform.position = Vector3.Lerp(transform.position, desiredPosition, Time.deltaTime);
}
}

The provided code snippet is for a camera follow script in Unity:

  • Line 3: The CameraFollow class inherits from MonoBehaviour, allowing it to be attached to a camera GameObject.

  • Lines 5–6: There is a public Transform variable target, which should be assigned the player's Transform, and a public Vector3 variable offset to set the camera's position relative to the player.

  • Lines 8–18: The Update method runs every frame. Inside Update, it first checks if target is null (no target assigned), and if so, it exits the method early with return. If there is a target, it calculates the camera's desired position as the target's position plus the offset. It then sets the camera's position to a point interpolated between its current position and the desired position using Vector3.Lerp, which smooths the camera's movement towards the target over time, based on Time.deltaTime for frame rate independence.

The CameraFollow component
The CameraFollow component

The final output is as follows:

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved