It’s been a while since I last posted anything here. I had intended to continue with my wave shader tutorial, but I had somewhat lost interest in the project. I may revisit it at a later date. Anyways, this is going to be the first in a series of short form tutorials meant to help people who already have some programming experience but might not necessarily know how to approach certain game specific problems.
Today I want to cover a fairly simple concept that more inexperienced programmers might struggle with; how to make a player controller detect and react to steps or stairs. This tutorial assumes that you already have a player controller with basic locomotion, and an intermediate level of programming experience. I’ll start off with the theory behind it and then showcase an example of how it can be implemented in the Unity Engine.
Theory
For this example, I’ll use a basic first-person controller with a capsule shaped collider. You could use other types of colliders or player controllers, but a first-person controller is fairly easy to visualize. Your character/player controller should should look something like this in your engine of choice. Make sure you’re controller’s point of origin is at the very base of the collider.
Next, you will want to cast two different rays in front of the player; the first from the point of origin, and the second from a point above the player’s origin. The first ray should be cast short than the second ray, as shown in this diagram. You will then want to programmatically use these rays check for collisions in front of the player.
If the bottom ray detects a collision, but the top ray does not, then the object in front of the player is a step. If both rays detect a collision, then the object in front of the player is a wall. If it is a step, you can move the player upwards.
Note: the reason the upper ray is cast out further is to account for slopes. If both rays were the same length, the bottom ray could hit the slope, and the top ray might not. This could be detected as a step. It’s better for the top ray to either not detect a collision at all, or detect the slope and treat it as a wall.
Unity Implementation
Here is an example of how to implement stepping into C# script in the Unity Engine. This particular example relies on a player controller that has a RigidBody component. This example also assumes that you already have your own code for locomotion and ground collision detection. Some values are hard coded here, which isn’t exactly the best practice. Use your best judgement for your own implementations.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Player Movement System
// Created by Jared J Roberge
public class FPS_Controller : MonoBehaviour
{
// This bool is used to record if the player is on the ground. You can replace this with whatever you're using for ground detection.
public bool isGrounded;
public RigidBody rbody;
private void FixedUpdate()
{
RaycastHit lowerHit;
RaycastHit upperHit;
// Assumes origin is at base of collider
Vector3 lowerCastOrigin = new Vector3(transform.position.x + 0.3f, transform.position.y, transform.position.z);
// Same origin with modified y coordinate
Vector3 upperCastOrigin = new Vector3(transform.position.x + 0.5f, transform.position.y + 0.6f, transform.position.z);
float castDistance = GetComponent<CapsuleCollider>().bounds.extents.z + 0.2f;
if (isGrounded) // Player is on the ground
{
if (Physics.Raycast(lowerCastOrigin, transform.forward, out lowerHit, castDistance)) // if true, object is in front of player
{
// if false, object is short enough to step over.
if (!Physics.Raycast(upperCastOrigin, transform.forward, out upperHit, castDistance + 0.2f))
{
rbody.AddForce(Vector3.up * 0.4f, ForceMode.VelocityChange);
}
}
}
}
}
The X position for the two ray casts are placed outside of the capsule collider so as to not detect a collision with the player. You could also perform a check to detect and ignore specific layers. Layers can be omitted using an override of the Physics.Raycast method in Unity.
Anyways, this was just a really quick and simple guide on how to make your player controller react to stairs and steps. This just a very rudimentary implementation to help put people on the right track. You can further enhance your step detection with a third, diagonal raycast to find the height of each step and move the player upwards accordingly. If you’re just looking for a quick and dirty solution to get you started though, my implementation here should work quite nicely.
Leave a Reply