Luke Haslett's Portfolio
Game Development Blog
As mentioned previously, I’m utilising the free Infinity Blade assets from the UE4 Marketplace, as my project focuses on tech and design. Despite this, it’s still important to practice intelligent modular level design.
I don’t want my game to give a visual impression that feels repetitive and boring. So, with my basic framework already setup in a base room, I can make child classes from it to look different whilst still performing in the same way.
For now, I’m only building functionality so the rooms contain only floors and walls. Once the core gameplay and mechanics are developed, I can return to populate the rooms with environmental assets and general polish.
First, I built a basic spawning room, as seen in my last blog post:
Next, I duplicated the spawn room to use as my end room that caps off all the remaining spawn points:
Then I made some general rooms to fill in the map:
Finally, here’s an example of a built map:
An important characteristic of Diablo’s gameplay is that any wall or large object that sits between the player and their character, fade out of sight. This allows the player to clearly see what’s going on in the environment around their character.
This is something I wanted to replicate in Grinders Keepers, and luckily I found a method for doing this on the Unreal Engine community forums.
The first thing I needed to do was setup a material instance for my fading actors. Seeing as I’m using Infinity Blade assets, I made a copy of some of these materials and changed their blend mode to translucent, whilst adding a scaling parameter that I could access for the opacity.
Next, I setup a new actor for a modular wall piece and added the materials to a static mesh component. When the actor is created, it creates dynamic material instances and sets them as variables, which will be used to get and set the opacity.
Following that, I went into my character pawn and attached a collision box to the camera’s spring arm. So whenever there’s a component overlap, it casts to the overlapping wall and either hides or shows it.
Additionally, I added a broken wall asset inside the walls so that it would look more effective, otherwise when the walls disappear it could confuse the player into thinking there’s a space to move through.
The walls of the dungeon will now disappear like so:
After my successful test in random level generation, I began setting up my core project using a top down template as this fits well with the gameplay characteristics I have in mind.
I started by building a standard initialisation chain to organise the order in which the engine constructs my managers, character, controller, spawn system, etc. I also replicated the scripts I’d written for building maps.
Something I noticed though was that when I was capping off the open ends of the map with custom “Room End” pieces, I was utilising a similar logic system as the normal map generation. This logic being: “Check to see if the collision boxes from the room class return true. If so, destroy the room tile, remove the spawn point, and run back through the whole event”. Except I had forgotten to put the spawn point removal in. No worries, I thought, I’ll just drop it now. But then I was curious to see how much of a difference something that small could have on a project. So I ran some numbers.
I printed an integer to the screen that incremented each time the event ran until it finished capping off the map. I did this with a 10 room map, and recorded it 10 times without the spawn point removal, and then again with it. This was my result:
Using simple math, we can see that the average before is 18.5, and after is 8.9. Meaning the engine runs through the event 51.89% less, which is an incredible amount in itself.
So, naturally, I repeated the test for different room sizes:
Now we can see that for 20 rooms, the percentage decrease is 52.97%, 30 rooms is 53.2%, 40 rooms is 51.86%, and 50 rooms is 49.26%. Making our total average 51.84%.
This is a really interesting statistic, and even though the scope and scale of my project isn’t very large, for a project in triple-A development this is a good example of how important it is to script efficiently and micro-manage with small modifications like this. Otherwise, the more you overlook your code, the more instances like this stack up and can negatively impact the game, as well as the user’s experience.
For a lot of the work I have planned towards my first milestone, I have experience to support the confidence in my approach. But the one thing I don’t have practice in is map generation, so I decided to tackle that first.
With the system I’m employing being random level generation, I’ll need to use modular level pieces in my level design, and if I’m making multiple instances of similar rooms it only made sense to handle this with a class hierarchy structure. So, I made a base room with a few common variables, basic functionality, and only a collision box.
Using this as a parent class, I made a few variations of room tiles that I could use to test my script.
For the script itself, I spawn an actor at the start of the initialisation chain that will handle all the information of the rooms. At this point, the only information is an array of spawn points for each room tile that adds and removes available spawn points dynamically. I will also use this manager system later to handle more information about gameplay, like if the room is going to contain monsters, traps, loot, or a puzzle.
Next in the script, I run a custom event that checks what the predefined map size is. If we haven’t reached that amount we spawn a random room from an array of room tiles, to a random spawn point in the manager’s array of spawn points.
Then, we do a check to see if the collision boxes from the room class returns true. If so, we destroy the room tile, remove the spawn point, and run back through the whole event. But if false, we feed the new room’s available spawn points into the manager’s array, decrement the map size left to spawn, and run back through the event.
What we then get is this:
The finished version won’t have a delay between rooms, I added this for the recording to show the spawning noticeably working.
Something to note with this style of map generation, is sometimes a room can spawn alongside another, which presents a doorway that leads into the back wall of the adjacent room.
However, I can deal with this by making a non-interactable door or flush wall visible on the room tile during the collision checks.
Finally, after the map has been made, I run another custom event to cap off any leftover spawn points that lead to nowhere, using a room tile with no attachments available.
There are other methods to random map generation that can involve using 2D grids, Voronoi diagram algorithms on random polygons, or digging rooms and corridors with instanced static meshes like the example project from the UE4 marketplace. But I decided to go with a simplistic approach of trial and error array checks as the overall scope of the project is small and the method is fit for purpose.
Before I start developing my game in engine, I need to conceive a clear vision of how the different features of my game are going to look, act and feel. This is done by producing an industry standard Design Document that includes an overall guideline for the various aspects of the development process.
Most of the design decisions for Grinders Keepers are relatively straight-forward, as I’m exercising established convention of the genre, but one of the qualities that I need to consider is Art Style. Now unfortunately I’m not an artist, and my project demonstrates that with its focus on the design and tech side of game development. Therefore, I’ll be using existing assets provided on the Unreal Engine Marketplace. Fortunately, Infinity Blade released a considerable range of medieval-fantasy assets that support my concept for the game.
Welcome to the development blog for my final year university project! I thought it would be a good idea to share my philosophy and process via a regularly updated blog, so I hope you enjoy and feel free to comment or send me any questions.
For my Final Year Project, I’m going to develop a dungeon crawler game called ‘Grinders Keepers’.
The game will be built in Unreal Engine 4 and utilise the engine’s featured development systems in order to create a fully playable game that boasts a range of commonly found features from the genre.
The game will allow the player to create their own character and play through randomly generated dungeons, collecting loot and progressing their character through traditional character development in the form of a conventional levelling system.
In addition, the project will feature level editor capabilities that allow the player to build their own map layout, before subsequently being able to play through it.
I have chosen this project because, not only is it a genre I enjoy, the experience aligns with my aspirations to someday work for Blizzard, and I’m building my portfolio to support that. That being said, I’m using the Diablo franchise as the inspiration for Grinders Keepers, and I’m keen to explore the style.
In order to achieve this goal, I have set development milestones over the year;
The first milestone is to take care of the core gameplay and mechanics by the end of the first semester, and will include:
The second milestone is to handle the fully functional level editor for March, and will include:
The final milestone covers the logistics of finalisation for the end of April, and will include: