In this update, I implemented the main character’s movement functionality. I’ll discuss the problem (even though obvious, we just need the character to move, but there were some considerations), the result, and some useful information I came across while implementing the feature.
I would say that the most important part of a videogame is for the player to be able to interact with the game itself. The most common way of achieving that would be via the movement of the main player (however there are exceptions, e.g. visual novels). For our use case however, a platformer game, we certainly need a movement functionality for the main character.
After starting the movement task, I started brainstorming on how the movement functionality would be implemented. My first thought – the simplest solution possible – was to detect a keypress, and while a key is being held down, move the character on the X/Y axis by changing its position. This makes sense from a software engineering standpoint, since it is the simplest way to get to the required result, however in the context of developing a game, this would mean having to roll out my own implementation of gravity / external forces, so I quickly got to the assumption that there had to be an easier, possibly built-in, way of moving an object.
Having done the Unity tutorial projects, I knew that I had to somehow interact with my 2D Rigidbody object. A quick search for the Rigidbody documentation gave me several results, but none of them seemed like anything I necessarily needed, so I looked at the Rigidbody2D definition directly.
Here, two elements caught my eye, the AddForce() method and the various velocity attributes. After a quick stack overflow search on forces vs velocities, I found out that the velocity attributes are the thing I was looking for, since I needed snappy controls of my character, and not necessarily a realistic physics-based approach.
Here’s the answer in that discussion:
After setting the velocity of my Rigidbody, I found that it successfully moved. I however needed it to respond to keypresses (setting the velocity in the Update() method made it constantly move). After a quick documentation search for the keyword ,,Input”, I found the InputManager class where the developers show an example on getting the input for the X (horizontal) axis.
Input.GetAxis() returns a float from -1 (indicating left), to 0 (indicating a button not being pressed), to 1 (indicating right). I used this functionality to implement the horizontal player movement.
NOTE FROM THE FUTURE: Looking back at the documentation, the Input Manager is a legacy feature, and I should have used the new Input System package instead. I have noticed this error in week 12, when I was adding source links to all the development diaries, and as such I continued using the legacy Input Manager throughout the project. Keep this in mind if you are following the diaries as a tutorial.
Now that I have implemented the horizontal movement, I needed to implement jumping. Having went through the Input Manager documentation, this did not seem like a hard task. I found out that the Input Manager differentiated two types of inputs, Keys and Buttons. See the screenshot below:
Assuming Buttons were solely used for controllers, I searched for the keyword ,,GetKey”. It did not seem to show me anything particularly relevant, however in the subheadings of the links, I saw the frequent usage of the Input.GetKeyDown() method.
However hardcoding keys did not seem right, so I also searched for ,,GetButton” paired with ,,jump” and got several results that seemed to do what I was looking for.
After setting the Jump button to be set to the spacebar key, I implemented the spacebar check together with adding vertical velocity on jump, and had a working jump functionality.
I have learned that game development differs quite a bit from traditional software development, at least for basic games that do not necessarily need to optimize each algorithm. As someone with software engineering experience, my problem-solving abilities of finding the simplest solution that requires the least number of external dependencies (ideally no dependencies), slightly hindered my game development speed, as I tried to implement every mechanic on my own, and did not think to check if Unity could do the work for me.
On the bright side however, I believe that implementing each mechanic on your own isn’t necessarily a downside. I have seen a lot of software developers rely on libraries / frameworks without even knowing what problem each tool was made to solve, because that is simply the technology they started with and/or are used to using and have not looked deeper beyond the abstractions. Implementing mechanics on your own allows you to understand how higher-level abstractions work under the hood.
A great example of this would be Unity’s MoveTowards() function. I would have never thought that there exists a function like this, so my first instinct would be to calculate a vector between two points (get the direction) and then move the object in the calculated direction by some amount. And unsurprisingly, after I checked how MoveTowards() was implemented by the Unity developers, it does exactly that. See the screenshot below:
So, my final takeaway from this week’s update is that Unity is way more capable than I thought. It gives you the tools and abstractions needed to develop an MVP (minimum viable product) as quickly as possible, however for the sake of learning, it is not a bad idea to try to implement these abstracted functions yourself.
I have learned how velocity works in unity and how it can be used implement movement mechanics.