Devlog 9 - Modular Movement System
Throughout Corrupted Castle, our hero has a lot of different movement abilities that he can use at his disposal to traverse the world.
When I designed this, I wanted a system I would be able to easily expand upon, as well as add more movement abilities without rewriting code for the older ones, or adding a bunch of if else statements.
0.5 - Prerequisites
Before we can begin calculating the movement for the player, we need some sort of framework to actually move the player. Unity has the Character Controller and Rigidbody components, which both allow us to do just that. The Rigidbody is physics based, while the Character Controller is not, which allows to define our own physics. For the remainder of this write up, I’ll be using the Character Controller component, as it allows us to be much more intentional with exactly how the player moves throughout the world, and it’ll merely handle collisions for us.
1 - The Movement Machine Idea
To be able to handle all the movement we want to apply to the player, we’re going to want some kind of manager to handle all the different actions the player can take, as well as provide each one with the necessary information each one would need, like the current velocity, whether or not the player is grounded, etc. We also want the Movement Machine to be able to enable and disable any scripts at will. This is useful for abilities that shouldn’t be interrupted. For example, we wouldn’t want the player to be able to dash in the middle of an attack. This also keeps our code clean, scalable, and minimizes direct dependencies. Modularity is a common design pattern in programming, and it’s incredibly helpful when creating a system that has a lot of moving parts.
2 - The Player Mover Interface
Before we can begin managing the player movement, we first need to define what exactly moves the player! My approach was to create an Interface named “IPlayerMover” (the ‘I’ being indicative that it’s an interface). The IPlayerMover simply does two things: it gives us a way to:
A) Define all our movement actions separately (walk, dash, gravity, etc.)
B) Store all the movement actions in a list by creating a list of type IPlayerMover
C) Easily grab and apply each movement force directly to our player’s overall velocity
Given that IPlayerMover is an interface, all we have to within the interface is define the way we obtain our force that we’re going to add. I defined this as a function that returns a Vector3, and we’ll call this UpdateForce(). This simplifies how the Movement Machine interacts with each IPlayerMover, and makes it easier to work with over time.
3 - The Movement Machine in execution
Now that we have our player mover interface, we can begin defining how the machine should work.
If you don’t know already, when working in Unity, FixedUpdate should be the only update loop that we use when we’re applying the movement forces, as FixedUpdate runs on a consistent time step, rather than being frame dependent. This is incredibly important when dealing with movement, because if our code was frame dependent, a drop in FPS could potentially teleport our player outside of the playable area if the game froze for long enough.
To begin, we want to define a list of IPlayerMover at the class level. This allows us to only have to cache all the movers once at the start of the level, which is incredibly important given this is an expensive operation. We can define this as List<IPlayerMover> playerMovers = new(); and then inside of Awake(), we can call playerMovers = GetComponents<IPlayerMover>(); This will get each and every IPlayerMover attached to the player, and store them for later.
Now inside of FixedUpdate, we’re going to want to create a Vector3 and call it forceToAdd. This is going to be the sum of all the current forces that will be applied to the player. Now that we have a list of all the Movers, we can iterate through each one and add it to the forceToAdd variable. BUT we’re going to ensure that the mover is enabled. This is to assist later on, and support the ability to disable player actions at any time. This code will look something like this:
foreach (IPlayerMover mover in playerMovers)
if(mover.enabled)
{
forceToAdd += mover.UpdateForce();
}
Finally after iterating through each active mover, we can apply forceToAdd by using CharacterController.Move(forceToAdd);
This lays the foundation for us, and we can then move onto creating a class for each action the player will have throughout the game.
4 - Application
We can now create and add a Player_Gravity component that derives from IPlayerMover and MonoBebavior. To believably create gravity, all we’d have to do is store the current gravity as a float at the class level, and then inside UpdateForce() we can subtract -9.8f from it, and then return Vector3.up * currentGravity. We also want to make sure we reset currentGravity back to zero when we land on the ground, and we want to make sure that we only subtract from currentGravity when we’re NOT grounded. This prevents the player from building momentum while they’re just standing on the ground.
5 - Extras
There are still some other things that we’ll need in order to make everything work properly. In the above section I mentioned checking if the player is grounded or not. We’ll need some way to know if the player is grounded, and the best way to do this is to perform a ray cast or sphere cast inside of the Movement Machine itself, and then we can make public getter variables so that all our movers can access this information, without having to perform these calculations multiple times for the same reason. Another good set of code to have in our Movement Machine are ways to disable and enable certain actions the player has. In Corrupted Castle, I created a function to disable all scripts but one, which you can pass the one that will stay on as an argument. This is used in the dash ability, so the player can’t interrupt it. We’ll of course need a way to re-enable the movers, so it’s good to have a ReenableAllMovers() function as well. Disabling and reenabling scripts can be finicky, so I would recommend using them sparingly.
6 - Conclusion
While there is still a lot to tell as to how the player movement works, I hope this gives you a decent peek behind the curtain as to how the movement system works, and gives you some ideas on how to make a modular movement system in your own projects in the future! And if you read this with no coding background, I hope I didn’t bore you too much! Thanks for reading :)
Below, you can find some of the code used for the movement machine used in Corrupted Castle!
IPlayerMover - Interface Declaration

Player Movement Machine - Update and Apply Forces (Run in Fixed Update)
IPlayerMover Example Script - Gravity
Get Corrupted Castle
Corrupted Castle
Status | Released |
Authors | trweening, Allie Almikieieva, Joe Morris, CalebCaliber, KnightIsiah, Tuscuu |
Genre | Adventure, Action, Platformer, Puzzle |
Tags | dev, elemental, knight, No AI, Pixel Art, sourcecode, Swords |
Languages | English |
More posts
- Devlog 12 - Props| Environment38 days ago
- Devlog 11 - Animations38 days ago
- Devlog 10 - Script Stealing!38 days ago
- Devlog 8 - Finishing the Boss45 days ago
- Devlog 7 - Stylized Environment!59 days ago
- Devlog 6 - Creating the Final Boss: The Dev!66 days ago
- Devlog 5 - Enemies!66 days ago
- Devlog 4 - Moving Platforms and Elevators!66 days ago
- Devlog 3 - Level Design66 days ago
Leave a comment
Log in with itch.io to leave a comment.