With starting my development log I first took over what I created from my problem solving, being the starts of a main menu from using the canvas in Unity 2D.
The making of the UI main menu was a lot easier than I originally thought as without even having to use a video or tutorial, it was repeating the process that we had already learnt in class to add buttons to a canvas. I kept it simple for now as I didn't focus on the art and wanted a framework for my game first. However I did end up using this video to set up the buttons as I didn't fully remember how to set them up so the event system work and activates whatever the buttons are set up to do. The Background art / Title Screen was the use of my concept art of the landscape to visualize the location of my game with the Logo I had came up with in problem solving overlapped.
So I set this up as my 1st scene, the main menu and used a script called "gameMaster" to control the actions of this scene.
It controls things like the toggling of the Canvases for UI to be visible and also controls the loading paths like what's activated or loaded when a button is pressed.
<- the script is attached to the Main camera of the scene and everything is attached to the Main Camera
Here is an embed from Github of the script.
Here specifically are the 2 functions I created for the 2 Main menu button named Start and Quit. I was originally struggling with how to do multiple scene loading and the code for it. Rather than go back to previous projects to find out I used this video made by Unity on multiple Scene workflow and followed their guide on setting up loading of multiple scenes which made it a lot easier.
The video also included a guide on how to do a loading bar, which I decided then to also add to the project for loading my game scene.
All this needed was a few functions that hid the Main Menu canvas and displayed the loading screen. In the end it wasn't too difficult to set up but the maths behind the set up of the loading screen was a bit complex with setting a progress amount to be equal to the fill amount on a sprite. It would end up looking like this before loading the next scene (however due to how simplistic and non demanding the next scene is the loading screen is hard to see, but it works nonetheless). (below is image of the loading bar)
This then created a finished Main menu. It lacked any in depth visuals, sound or more specific options or settings but was fully functional for starting and quitting the application.
I then started to work on my prototype level scene, or my gameplay to be specific. This was the continuation of what I had already made in my problem solving as well. Using this tutorial to add movement to my sprite (sprite was used from a free Unity 2D asset pack for barbarians - fitting for medieval).
This led to my scene looking like to start. The tutorial wasn't too complex and was easy to follow and essentially comprised of using a pre built "CharacterController2D" Script and manipulating it using a "Player_Movement" Script.
(The scene is just set up with a Camera on the player to follow, the player sprite with 2 colliders and a rigidbody then its 2 movement scripts and a floor of a long rectangle sprite with a box collider).
Scene Hierarchy
Player_Movement Script:
CharacterController2D Script:
These 2 script combined allowed for basic character movement of back & forth, jumping and crouching and this was all following the tutorial.
This video shows the basic movement of the script:
However I wanted to expand on that moveset using my own knowledge to develop my game further (knowing movement was going to be an important part and something I would like to focus on) so I started editing the player movement script. This was also when the difficulty started to ramp up as I was going over my own abilities and knowledge rather than following a guide.
This was making a sliding, sprinting and dodging mechanic . I went over crouching, sprinting and sliding in my problem solving. Although I forgot to mention how I had to do some additional problem solving of my sliding mechanic as it originally just went on forever and that's where I came up with the idea to use wait for Seconds to then toggle a bool to false which is required to be true for the if statement of sliding to go through. However I couldn't get this working at first and instead thought about the use of Coroutines, since I had just learnt them recently and seem them used before in this same scenario of WaitForSeconds I did create this coroutine which then worked and allowed for my sliding to be stopped.
But I then created a dodge mechanic, Since all the movement was physics based the dodge fit right in as it was also physics based and was made using my knowledge of creating a jump mechanic from previous projects. All it needed was a Function that Added force in the direction the player was moving.
This was the script that controlled the dodging and it worked well, the force variable (27f) needed tweaking to make it feel not to fast or far but the function itself worked and did make the player dodge. The only problem I found was that you could spam it and dodge as much as you wanted which allowed to player to move way too fast and instantly cross the screen. To fix this I created another waiter Coroutine to delay the function from being able to be called again. I also edited the waiter Coroutine so you couldn't slide and dodge at the same time.
Here is a video of me showing off the more developed movement mechanics like: sprinting, sliding & dodging.
In the end the development of the basic and more complex movement wasn't so hard and I was very happy with how it turned out. There were a few tweaks to perfect speed and to get things working but overall the movement turned out fluid which was what I was aiming for.
To make this Scene of the prototype level be loaded properly from my other main menu Scene using the start button and loading screen required the setup of another script which would be attached to the Main camera, otherwise the screen would be blocked by a finished loading bar.
This simple Scene unloader script was the fix: which just unloaded the Main menu Scene after this one was loaded. (the 0 in unloadsceneasynce is the 1st scene, aka the main menu).
So then I had a beginnings of a game with a working Main menu.
The next thing I worked on was improving the Camera, because originally I just had the camera follow the player one for one and it didn't look to great even though it worked it felt very dead and still and just didn't feel good when playing. So I then I used Unity's addon called Cinemachine. I followed this tutorial for CineMachine in 2D to make my camera look and feel better in my game. ( CineMachine 2D tips )
In the end this created a dynamic camera, but it still wasn't perfected and I did a bit more tinkering. Before this however I added a cursor to my mouse in the game as I wanted not only a custom cursor but wanted to use it for combat and to utilize the mouse position for dash attacks or other potential things like if I added a bow and arrow.
I created this crosshair sprite in photoshop and then added it to unity as a sprite with a script so its position would always be the same as the mouse cursor.
In the end it wasn't too difficult to set up as I used the video linked below to get help with the code. I reused/repurposed the code from the video on getting the mouse position to make my cursor. The only slight issue was that it's a little laggy and jittery when moving the mouse however I couldn't find a fix.
Here's a quick video of the cursor in action, it follows the mouse position but also hides the actual mouse cursor 'using Cursor.Visible = false;' in the code.
But after I had this custom mouse set up I then started tinkering with cineMachine as I wasn't too happy with how the camera was following the player. As I had the settings the same as the 2D Cinemachine tutorial using the "Framing Transposer" virtual camera setting however I found that I preferred the 'Orbital Transposer' as it fixed a major issue of the previous mode I was using. That was that when starting up the game sometimes the camera would be stuck in a weird position from the player either too forward or behind from where I move my cursor from the start. However in this mode if you dont move the camera for a few seconds (by staying still) it will automatically realign and recentre itself, fixing and issues of camera position. Another positive of this mode was that it allowed me to set up a secondary tracking so that not only did it track the players position for the camera but also was affected by the mouse cursor too as it is also affected by an option player input, aka the mouse's x axis.
Another feature I set up was the "Camera mapping" Collider which was attached to the CineMachine camera as a 'Confine2D' so that the camera couldn't move outside of this set up collider area, essentially preventing your camera from moving out of the play space even if the player isn't in it. (green is the collider/camera border)
This was a massive improvement over the prior case and here's a test video of it:
This is also where I found some jaggedness or lag in my characters movement which was fixed by setting the player's rigidbody Interpolation to Interpolate rather than none.
But now I had a much nicer camera movement with a cursor.
Then I tried to add some animation with an animation pack that came with the barbarian sprite using this tutorial:
As I wanted to work on combat but I thought I needed some animation first to go with the movement I had already set up, so then I could add some combat animations. However this is when I ran into some difficulty and the reason for my currently commented out animator code in my "Player_Movement" Script.
As I started running into some difficulty when setting up the animations. Mainly with softlocking my animations leading to either some not playing, some not lasting as long as they should and some being stuck on screen. This was quite frustrating as I had no clue how to solve my issues of getting the animations working: so Instead I put it on break to work on later, including the combat. To instead work on other parts of the game.
So Instead, since I couldn't get my animations working properly at all, I worked on the Hud for my game. This includes the prerequisite for a health bar, possible stamina bar depending on how combat was set up, any score/collectables (like money), ammo if adding any weapons or items that use a resource and an options/pause menu button and anything else later I might need. For visuals I used my designs from my ideas generation where I created some finished UI designs/concepts.
These were originally set up for the bottom of the screen, but after trying it out and having the UI at the bottom of the screen I quickly learnt that it would majorly obscure the players position since rather than in my planning of having the character in the middle of the screen, I had him nearer the bottom. So to fix this I simply inverted the sprite and affixed it to the top of the screen. (I split the UI into segments for better use and practicality).
This made my game now look like this:
I then continued my Hud by adding a pause button and menu, a button the cursor could click to toggle the "pause menu". I used a previously made settings wheel/cog for the icon and attached it to the board in the top right of the screen.
I then created a new "LevelMaster" script to be able to manage this Canvas/Hud and create functions for the UI such as toggling the pause menu when clicking this settings icon.
Level Master Script:
This was a collection of functions the UI would use to display or hide features or to get some to work. For example adding the 'pauseMenuButton' function to the settings button on the canvas so that it would toggle the pause Menu when the button was pressed. But also making sure the pause menu is inactive at the start of the game. Then giving the quit option inside of the pause menu. (the pause menu is a separate canvas to the general UI canvas and is displayed over the top of the normal UI when activated).
Overall I was quite happy with how these basics of a Hud turned out and with how easy it was to set up, especially when compared with the animation.
The only problem was that the cursor I had set up doesn't overlap with the Hud pause button because one is a sprite in the game screen and one is an image on the canvas. I looked into a way to make it so the cursor sprite would always be displayed on top no matter what but even when moving it to the canvas because the pause button is an image I couldn't find a fix for it to always be displayed on top.
Another problem you can see is that the normal mouse cursor is still visible at first, this is because the code that disables the mouse cursor is called on the game's "Start" so if the mouse cursor is currently outside the play area when the game starts/loads and then comes back in the code would have already ran meaning the original cursor is still on screen. Although this is an issue now, I believe once exported to an exe this problem would no longer persist as there is no button to click to start the game and you'd be loading into the level from the main menu a.k.a the cursor would be inside the game program at the time of the code going through.
Because the game at the moment was looking very barebones visuals wise, at this point I decided to add a background image after looking for royalty & copyright free art online and then editing the piece in photoshop. Then making it repeat itself (as I made sure to get a piece art that could be used as a repeatable background).
Leading to it looking like this:
So then continuing working on UI/Hud I moved over to score, leaving health to be done when I work on combat at possible animation.
This included adding a score function & mechanic but also a score display on the Hud. This started with the adding of a text mesh pro to my ui canvas so I could manipulate the text box via code. However because it was just hovering I added some more UI background for it then did some outline work and sizing so it was more readable. Then I created a basic Score script that was added to my main camera to track the score and update the value upon collecting a coin. Which is where I then set up a coin with a collider so that the player had some sort of goal or collectable along the way of the game.
But for the coin I needed a script so you could actually pick it up and for it to add score.
Overall setting up a basic scoring system code wise was quite simple as I had done this sort of system already before in my previous projects.
But now I had coins but no where to put them so I started to work on created a level layout, but for that I needed a tileset so I decided to reuse one I had already made for a previous project as it fit my dungeon aesthetic.
I used this as a tilemap and started painting, also adding a black background for all the underneath parts not covered by my background image. Then used a darker shade material to be able to use the tileset for a background as well. So then I started work on the level, but also I had to take sizing into account. It was quite difficult just to make the starters of a level. But then as I developed the level I needed to reshape my Camera mapping so that it would actually show where the player was going. This included the moving and resizing of almost everything in the game which took a little bit of fine tuning.
So the level and game looked like this:
Then I spread some coins out to fill the dead space and whipped up a sprite for some spikes for a static enemy so you die when touching them.
The spikes were kind of difficult because even when reusing the script for the coins there was some troubleshooting so that the player would actually collide with the spikes... However it turned out that my problem lied in using a box collider rather than a box collider 2D.
Here is the temp script I was using before I then set up a death and restart in my game:
Then I started to work on a death screen, to quit or restart the game if you die. This started with reusing code from the pause menu as it was very similar using a canvas. I created a death title in photoshop using a brush tool and some colour work.
and to make the death screen pop out I added a transparent black overlay to make it visibly over the top of the game.
Then I coded the canvas into the game, which just required the tinkering of my level master script and then adding a variable on my spikes script so that it would trigger the menu. This is the code for the spikes after updating it.
However then I needed to set up the buttons within the death menu, the quit was simple as it was re using the same quit function for the pause menu however the restart level was more difficult due to having issues with reloading the same scene and keeping the old one and the menu being stuck on screen. So it was more difficult needing to tweak the code and order so that it fully reloaded the scene. I couldn't in the end just reuse my original loading code. As such this didn't work:
So I tried looking up some help in forums and found this line of code:
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
which then worked to full restart the game.
Now that my game actually restarted on failing it was time to set up a finish for the level. This I thought could be a key/gate like system where at the end of the level there is a door but you cant open it or go through or finish the level until you acquire the key which could be gained from killing enemies or from a location in the level (platforming).
These are the gate and key I made in photoshop:
As I had never done a finishing system I had some difficulty starting it however I had a good idea how to structure it code wise.
This is the code I set up for my gate:
and then here is the key:
I did some tweaking in some sections after, code wise, trying to refine things. Like when you die or the game ends you get the normal cursor back and it disables the UI so you don't run into any overlap issues. This then led into the development of the final displayed screen when you win the level. This was more difficult because after creating the visuals I needed to set up the code to display the final score. (there was also the UI not being disabled but in the end I didn't mind and it worked still).
In the end it became quite difficult to wrap my head around using a score and final score Texts but by following this video it became a lot simpler and I was able to get my final score working.
and finalScore script:
At this point I essentially had a finished platforming game. There was a goal, a win and lose mechanics. The only thing lacking was animations, sounds and the fact there wasn't much of a level. Therefore I had covered everything I wanted to so far, other than one of the most important and harder things: Enemies and combat which is worked on next.
However first I added an image to the UI that displayed whether or not you had the key yet. Another thing was readjusting my slide speed as the character moved way too fast and for too long so I tweaked their variables in the PlayerMovement script. Also this is the new key script code for toggling a key on the UI.
So then I moved onto combat but started with some basic animations so I could tell when there was attacking or not. For that I followed this video:
This gave me some animation, the jump wasn't working but it was enough to understand what the player was doing rather than being still as a rock. It wasn't too difficult to set up. But then I moved onto this second tutorial video to create some combat:
During this I set up my animations and affects for my players combat and enemy hurt/death. Also I fixed the issue with the player's jump by adding "HasExitTime" forcing the animation to finish before transitioning.
This lead to having working player combat vs enemies. Overall compared to how I originally struggled with setting up my combat it went a lot smoother and I managed to get a good set of animations working. However I didn't include animations for player crouching or sliding due to time constraints.
Combat + Enemy Scripts:
Since I had made quite a bit of progress I decided to show my game so far:
To then continue with the combat I needed to set up a player healthbar before then creating a system where enemies can move and deal damage to the player. In photoshop I used assets from my ideas Generation.
As I was struggling when it came to the code of a healthbar I looked into a few tutorials to then find this one to help me create the healthbar for the game. It was still difficult especially when it came to sizing issues but i got an updating healthbar in the end.