00.5 - The Interim - Current Progress Extended

Prelude

Hello all! Welcome to the next of my developer logs. I hope that everyone is doing alright! I do apologize for the brevity of this installment, my family and I are moving!

Contents:
â–¸ Hierarchical State Machine for player state management
â–¸ Camera system
â–¸ Stairs

Hooray!

Hierarchical State Machine for player state management

To manage the state of my player, I decided to create a hierarchical state machine (HSM). And what is a HSM?

A state machine that orgranizes states and orders them in order of relevance.

I opted to make a HSM because it allows me as a developer to encapsulate certain behaviors to only work in it's respective states.
> For example, if the player is currently falling whilst not inputting any keys, the player would be considered to be airborne and idle. Two states! If i was to make a regular state machine for the player, I would need to create an Airborne Idle state, and when the player lands on the ground, I would need an Grounded Idle state. With the HSM, I could create seperate states and reuse states that share common behavior. With the HSM implementation, I would create three states: Grounded, Airborne and Idle states. Those states could then depict Grounded Idle and Airborne Idle without having to create a hyper-specific combined state. Although it is more overhead, I feel that it will be beneficial in the longrun.

Onto my implementation:

At the top of the heirarchy, we have ROOT states: the Ground and Airbone states

From there, from either of those states, we can go into an IDLE, WALKING, or SPRINTING.

I have also implemented a crouching state that goes in between the root states and the movement states. I see the crouching state as an 'Optional' state. For example:

> We can go down the state machine where the player would be grounded, crouched, and idling (Not moving).


The top left text reveals the current state of the player by going down the root states and connected child states.




When the player is on the ground idling and the player jumping while providing no other input key.




Heres a look at how it'd look from normal player movement!

From each state interally, we can take input/external factors and use that to determine if we need to switch states. If we do need to switch states, we have an exit function associated with it alongside things to clean up the state's data. We also have to enter the new state and that would have some further logic. For example, if we enter the airborne state, we can set the players gravity higher or lower! It's best to think of the state management as a linked list starting from the root state and it's associated child states. Then, for each Unity update cycle, each state's logic is performed.

Camera System

With my vision, a third person perspective was needed. There was a standout Unity Marketplace package called Cinemachine that handles all of that stuff. But! I wanted to learn how to make one for myself :P.

Problem

The camera would go inside of solid objects so theoretically the player could look through solid objects. Normally, in third person games, the camera would "skid" along a hard surface instead.

So then, I thought of a simple solution that worked when I only had a flat plane object and the player only:

â–¸What I had in place before was just a simple check if the camera was below a certain y-coordinate and to push the camera's y-coordinate up to the surface of the object hitting with hard-coding.

Although this did work for a simple test, it is not good since its hard coded and not dynamic!


I've outlined the object the camera would be in and where the camera was before the fix (blue circle)



I drew a 2d representation of what was happening:


The second row depicts what was happening before where the camera(RED) would go inside the wall. But we can shoot a ray from the player to where the camera is supposed to be(GREEN) and grab the point of contact(YELLOW), then we have our coordinate points of where the camera should be!

By using Unity's Raycast function, we can shoot a ray from the player's location torward where the camera should be in the world if collision was not in the picture. From the raycast, we can get data about the first "hit" from the raycast, in other words: the first point of contact with an object. With that, we have our general position of where the camera should be! So it would be as easy as setting that information to the actual camera position.


Great! The camera is in the correct position and not going into the wall object!



Stairs

Stairs. stairs stairs stairs...

With the way the player is currently being moved, a Physics Force is being applied to it in accordance to player input & camera position. The player could technically go up stairs because the player is a capsule, since it has rounded bottoms. The physics engine would take care of pushing the player up but it was SLOW and felt like going up the stairs and pulling a cart behind you.

Take a look at how it was before!


We can't innately walk up stairs!


To move up the stairs, an upward force must be exerted on the player to "step" up. For my implementation, a simple Raycast will do the trick! What we need to do is to first detect and then apply an upward force.

If you can notice it, theres a red line when we walk forward in the gif above, that's our raycast visualized!

This is actually a similar solution to our camera problem! We just need to check if we hit a stair. Now what is a stair? We can define it as two objects that are a certain distance away from eachother (one step). For this, we can use TWO raycasts. The first raycast is used to detect the player oriented face of the step and the other raycast will be used to detect the next step.


The red line would be our first raycast to detect the first step, then the blue line would be for the second step! If both raycats return a hit, we can apply our upward force!



Wonderful 🙂. Our steps seem to be working!


Afterword

Thanks for stopping by and reading this all! I hope to see you next time! Here's a picture of whats in the next log!


Have a good one! 👋🕷

linkedIn mail gitHub