top of page
Search
  • Brendan McIntyre

DevLog 04 - Creating the MVP

Hello all. This work that has been completed on the game has been all about creating the mvp (minimal viable product) version of the game. This means that the win and lose conditions of a contract must be implemented, along with some sort of main menu for the player to enter or exit the game. It’s safe to say that this ended up taking way longer than intended due to a number of small issues that took way longer than they should’ve to be fixed.

Damageable Goods

The first step in getting the mvp done was to create the necessary components that would trigger a win or lose condition. The first of these components is the ability for the goods to be damaged and destroyed by enemies. The way this is done in unreal is through a montage. Initially I created a similar anim montage that I had previously, using a notify state to call sphere traces between the specific points in the animation. However, the problem was getting a reference to the enemy to damage it as notifies have very limited functionality. I could’ve made it work by casting actors to enemy actors, but felt that this would be terribly inefficient. I tried to get around this using an interface, but since I have never tried to make an interface in unreal c++, it ended up not working out. So I tried to do it just using single notifies. These notify events get passed to the anim blueprint which does have a reference to the enemy character. From there, it calls a function on the enemy to initiate the sphere trace.



Since the event pushed out by the notify event only happens once, I needed to repeated call the sphere trace event until the notify event to stop the sphere trace is called. To enable the attacks to hit multiple objects at once and avoid doing multiple hits on the one object, every object that can be damaged by an enemy melee attack (at the moment it’s just the goods and player objects) gets added to a list of hit objects when it is damaged. As long as an object is on this list, it won’t receive a second call to damage it. When the end damage notify event is called, this list gets cleared so that these objects can be damaged again.




Now the problem was that the enemy would not initiate the attack montage when it got close to the goods. So I realised I needed to make changes to the behaviour tree. The first problem that I realised after doing some research is that I was implementing the “Is Within Target Range” check. Originally I implemented as a task. However, since this is a check and setting a variable, rather than an action, it made more sense for it to be done as a service. I also needed to add an extra node to handle the initiation of the montage. This node calls a function from a melee interface, which in itself plays the montage.



The final problem that occurred was that the original attack animation did not actually hit the goods object. So, to fix this I made some minor changes to the attack animation, lowering the arm so that it was guaranteed to hit the goods objects.



Wave System

The other of the components that needed to be created before working on triggering the win/lose conditions was the wave system. This would allow the win condition to be triggered when the player completes all the waves. Initially I attempted to create a c++ class that would be used to store the information and functionality for each wave; with this class being stored in an array on the game state. However, it turns out that I couldn’t find a way to make a generic c++ class that could be stored as a variable on another object. So after a bit of research, I came across data assets. Data assets allow for multiple variables, structs and even functions to be stored together, and multiple different data assets can be stored in arrays in other classes. It also turns out the c++ classes can inherit from the data asset class meaning that I can create custom data assets within c++, all of which is exactly what I wanted. I did have the thought that it might be annoying to create a data asset for every single wave, but I realised that it would likely be the exact same case if I managed to get a standard c++ class to work. The only slight problem is that data stored inside a data asset cannot be modified, so variables that change such as the number of enemies spawned within a wave will need to be stored outside of the data asset (most likely on the game state).

With that problem solved, I created my custom data asset class. The data asset holds data on the number of enemies that will be spawned in the wave, the different types of enemies that can be spawned, the ratio that the different enemy types will spawn at and the spawn rate. The data asset also has a function that handles spawning the enemy went told to by the game state.



Once I had the data setup for the enemy waves, I could begin to create the wave spawning system. I had to design a wave system that would spawn enemies at a fixed rate but then stop once the wave finished and not start again until the player called for the next wave.




This is certainly not going to be the final version of the wave spawn system. Since there is only one type of enemy implemented at the moment, there was no need to build the wave system to accommodate for the spawn ratio. On top of that, I plan to also have a different spawn ratio for each spawner in the level. However, to do that, I need to figure out how to properly make structures in unreal c++. I have attempted to do this but every time I try I get errors even though I have the exact same format as what I’ve seen other do.


The reason I like a ratio system for spawning enemies like this is that it is the best compromise between having a wave system that spawns different enemies without having to go through the tediousness of having to manually specify the order that different enemies will spawn in. The ratio system still does provide interesting and unique waves to the player but is much easier to adjust than the manual system.


One idea that I came up with during the creation of the wave system was how to dynamically create and adjust spawn locations. Initially I was going to have the spawn locations be a transform that is stored in the wave data. However, I quickly realised that this would be tedious when trying to add or adjust these spawn locations. This would usually involve me already just adding in a blank unreal actor and recording it’s transform. So, I decided so make a custom actor in c++, in which its sole purpose is to store the transform of the spawn locations while being an easily adjustable in the editor.



The game state can then store all references to these spawners in a list along with an index of which spawner it needs to spawn the enemy from. This means that the number of spawners in the level can be easily adjusted and the game state will still spawn enemies as intended.


Menu Creation

The final piece of the puzzle that needed to be made before I could create the win/lose conditions was to create the appropriate menu system. The first of these was the main menu. For the moment, the design of the main menu was focused on functionality rather appearance, as seen by its bare bones nature.



When the player begins the game, they are taken to the basic tutorial screen. This just consists of some text explaining the premise of the game and the controls needed. While I am fully aware that this is the worst format for tutorials, I want to focus on the gameplay engagement rather than the actual design of the tutorial for the initial playtests. However, the one of the first things I want to work on after the first playtest is to create a more engaging and sophisticate tutorial. I already have an idea of how I want to do it, plus I can get a better idea from the first playtest as to which aspects of gameplay might need a better explanation.



The final two menus that were created where the contract completed and failed menus. Once again, the designed for the moment went for practicality and functionality over appearance. These menus consist of some text saying whether the player succeeded or failed the contract, as well as two default buttons. These buttons either take the player back to the main menu or to quit the game. As more menus get added in future updates, these will obviously link to those as well.





Creating the Win/Lose conditions.

Finally, with everything else in place, it was time to create the win and lose conditions. The win and lose conditions for a contract are simple; the player wins when they defeat all enemy waves and lose if either themselves or the goods are destroyed. Unfortunately, I ended up making it not so simple for myself. Initially I wanted to have the game state store a reference to both the contract victory and lose widgets. However, it appears that you cannot store blueprint widgets on a c++ class. If I wanted to pursue having widgets stored as variables I would’ve had to learn how to make a widget class using c++ and that was something that I didn’t want to spend a huge amount of time doing this early on. So I decided to just to the condition checks using bools and have blueprint code create the widgets when the specified bools become true.


However, when testing the victory condition, the widget did not function how I intended. The problem was that the buttons on the victory condition could not be pressed (although if the enter key was pressed it would work), nor would the buttons visually change when highlighted. For way too long, I thought it was caused by various things such as using the wrong input mode, incorrect settings on the ui or how the victory condition was done. It wasn’t until I activated the win condition using a key press in blueprints that I realise the small issue that I had overlooked. The widget was being created in the tick function (which is needed to check the victory bool is true) which meant that the widget was being created every tick. So all I needed to do was add in a do once after the condition check and the menu worked perfectly.





One last key change that I made to the game as well was that I made a change to the UI. It remains to be seen how important a change this is, but I added in a bit of text that displays the number of enemies that are remaining. I figured it would be important for the player to know this but how correct I am about this will have to wait until I get some playtesting done.







What's Coming Next?

So that is everything that has been worked on since the last update. It took way longer than it should’ve, so hopefully things will pick up for the next update. Speaking of which, the next update will focus on adding in the last pieces of gameplay and getting the game ready for the first playtesting session. This will include the adding the ability for players to add in walls as well as a place for players to manage contracts and manage/update weapons. Finally, I also plan to add some effects to the game. So, until the next update, goodbye.

9 views0 comments

Recent Posts

See All
Post: Blog2_Post
bottom of page