Project Osiris – Devlog #1: Character Movement

One of the things that fascinate me about video games is the ability to tell stories and allow the player to be part of it. These immersive experiences are what make video games epic. I remember the tears I shed when General Shepard killed Ghost and Roach in cold blood after having a very tough time in the mission titled “Loose Ends” in Call of Duty: Modern Warfare 2. I was too mad at Shepard and I remember that I cried a lot when that cutscene was playing. Since that moment, my dream of creating a video game that tells an epic story has started. Today, that dream is in progress and I am finally ready to tell a story of mine

This is where Project Osiris comes in!

Yes, Project Osiris is a code name of a video game that I started developing on April 2nd, 2021 that tells an epic story about the ancient Egyptian civilization. I don’t want to get into details about the game in order not to spoil the idea but through the game the player will take a role of an Egyptian god who tries to restore balance in Egypt. The player will engage in epic battles, fight big monsters from the Egyptian Mythology and spar 1:1 with Egypt’s greatest gods.

I started with working on a high concept document that lays out the game in terms of functionality, enemy types and powers that each will poses. I have to say designing a game from scratch is challenging but fun. At the moment, I am working on the Game Design Document (GDD). I should be able to complete the full design of the game by the end of April 2021.

However, being a geek and someone who cant stop writing code, I jumped into unity and I started prototyping a basic third person controller. Yes, the game will provide the player with a third person view of the player. To make the game easy to port into other platforms, I used Unity’s new Input System in order to layout the controls for the keyboard. This is how the basic layout that I started with looks like:

Figure 1: The player input layout

The use of Unity’s new input system will allow me in the future to enable control use with ease and without doing any changes to the code. I have future plans into building the game for consoles, but it is too early to decide now on this. As you can see in figure 1, the player can move using the WASD buttons and can jump using the space bar and look around using the mouse. the MouseLook action is then liked to the Virtual Camera that is responsible for tracking the player. I did this by adding a Cinemachine Input provider component into the virtual camera, this will override the needs for the standard input.

Figure 2: Cinmachine Input Provider component

With this setup, I created a player character with the most complex graphics that any GPU can ever handle!

Figure 3: The player character

At this point I was ready to start coding a simple third person controller. For this case, I wanted to use Unity’s character controller to handle the movement and the ground check for me. I started with creating the below variables:

Figure 4: The controller’s variables

Afterwards, I initialized the input system for player controls and some other variables in the start and awake functions

Figure 5: The unity functions and initializations

You may have noticed that I tend to comment my code a lot. I do this because it is very important to make your code understandable by other people who may review you code or even be working with you. Also, a great man once said:

Always comment your code as if the one reviewing it is a serial killer who knows where you live!

Let’s get back to the code and examine the Move() function This is where the magic is happening. this function is divided into to major parts. The part where the player moves and we align the player forward vector with the camera’s direction and the other is to handle the jump. Here is the code that makes the player move in the direction of the camera:

Figure 6: The player movement section with respect to the camera’s direction

The code looks straight forward but I want to explain a bit the lie where I calculate the target angle. Imagine the the player is looking at a direction, call it x, now put a point at that line, then imagine that the camera is looking at another direction and plot a point on that line and call it y. These two line will intersect at some point and you want to calculate the angle between those two lines because this is the angle in which the player should turn in order to be aligned with the camera’s forward direction. The function that can calculate the angle for us is an Atan2 function.

Figure 7: Atan2 Function

As you can see in figure 7, the angle can be calculated by the function atan2(y, x). However, in our case the atan2 function will look like this atan2(x,y). The reason behind this is that we are facing the forward direction and according to tan part in sohcahtoa, the tan of theta is calculated by the opposite/Adjacent. Since we are looking forward (the direction of the positive Y axis) The opposite of the angle is a line parallel to the X-axis and the Adjacent is the Y-axis as shown in the diagram below.

Figure 8: the calculation of the the new theta

After calculating the target angle, I used the SmoothDampAngle function offered by Unity to smoothen the angle. Without the use of this function the player will snap to the new rotation, instead I wanted the player to have a smooth transition when rotating the desired direction.

The final thing that I did is to code the functionality for jumping which is straight forward.

Figure 9: The jumping code

The reason why I am caching the value of the yVelocity in a global variable is that I don’t want the y position to be overwritten every frame when the movement direction is calculated otherwise the player will jump in the current frame and will snap to the group in the frame right after it.

With this, I was able to create a basic third person controller that works like a charm. There are so many other things that I am planning on implementing but these are for a later blog post. Here is how it looks like:

Figure 10: The third person controller in action