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.
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 movementVector3 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.
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 buttonsfloat horizontalInput = Input.GetAxis("Horizontal");Vector3 movement = new Vector3(horizontalInput, 0, 0) * moveSpeed * Time.deltaTime;// Implement continuous forward movementVector3 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.
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 buttonsfloat horizontalInput = Input.GetAxis("Horizontal");Vector3 movement = new Vector3(horizontalInput, 0, 0) * moveSpeed * Time.deltaTime;// Implement continuous forward movementVector3 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 gravityfloat 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 transformpublic Vector3 offset = new Vector3(0, 5, -10); // Offset from the player's positionprivate void Update(){if (target == null)return;// Calculate the desired camera position based on the player's position and offsetVector3 desiredPosition = target.position + offset;// Smoothly move the camera towards the desired positiontransform.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 final output is as follows:
Free Resources