Castle Siege
Why I Made This
Castle Siege is a vertical slice of an Action-Adventure game made with Unreal Engine. I wanted to learn how to make action games in Unreal using C++ and blueprints. So in January I started taking a Udemy course on Unreal Engine. After completing the course, I wanted to challenge myself to make a game using the concepts taught in the course to prove that I had learned and internalized them. To do this, I used exclusively Unreal documentation and my notes from the course to build Castle Siege. This project gave me a chance to use Anim montages, Anim blueprints, C++, blueprints, and UI widgets without using any tutorials. I completed the course over 4 weeks and the subsequent Castle Siege project in over 2 weeks.
What I Did
- Implemented and scripted out a custom boss using inheritance, blueprints, and animation montages.
- Leveraged inheritance to build on existing mechanics such as creating a teleport and multiple switch pressure plate puzzle.
- Designed the UI, such as the Main Menu, Settings Menu, and autosave logic.
- Implemented and Designed the ‘Heavy Swing’ mechanic for risk/reward gameplay.
- Tuned the combat mechanics, controls, and enemy AI.
- Wired up the main character using Mixamo assets and modified game controller.
- Designed the pressure plate puzzle, created player motivation from coin mechanic, and modified the sample city of brass level to satisfy the vision.
What I Built Upon
- All assets such as animations, pictures, sounds, levels, and models were free assets that I found either through the unreal store or online.
- The core action combat system based around collision overlaps is an extension of the Udemy course.
- The pickups such as health potions, weapons, and bombs initial implementation were from this course as well.
Gameplay Programming
The Boss
While I’m not great at action games, I enjoy boss rush style games like [Furi]. I wanted to challenge myself to come up with an interesting boss and script out some custom mechanics for it. Given the limited animations I had available, I decided to create a ground pound and “bomb drop” style mechanic. This mechanic is powered by C++, a blueprint implemented event, and the animation blueprint to trigger notifications from the montage.
The mechanic itself is broken into 2 parts:
Part 1: When a “bomb throw” is chosen as an attack, the enemy moves to the center of the stage and triggers the ground pound animation, this was implemented in blueprints.
Part 2: During the animation, a few “animation notifies” are triggered. The first for triggering damage to anything underneath the boss during the ground pound. The second notification is to create the falling bomb. Both are triggered in the animation blueprint and they call these c++ blueprint callable functions.
One issue I noticed while working through the course materials was that iteration time was very long. Primarily due to manual testing inside existing levels and interactions with other mechanics. To solve this for the features I built in my game, I originally scripted out the boss using blueprints. In addition, I tested changes in a small level to reduce iteration time and isolate functionality. After I tuned and iterated on the mechanics, I ported any simple blueprint code to C++ and placed the enemy into the world.
Further Optimizations
One thing I noticed when setting up the main menu is the game would appear to freeze as it loaded up the first map. I decided to leverage Unreal’s asset loading to load the level as soon as the ‘start game’ is pressed, this way while the player is reading the intro screen, the game is loading the level for them. I used this technique to load levels as a player would get close to a transition volume in an earlier iteration of the game before cutting down the scope to a single level vertical slice.
I leveraged “pointer to a pointer” abstraction to refactor some laborious UI code around instantiating the widgets. This cut the overall code by about 60 lines. Lastly, I leveraged inheritance to reuse code from the 1 plate switch and quickly create a 2 plate switch.
Game Design
Boss
One problem that arose from the boss’s bomb mechanic is there originally was no damage triggered from the enemy pounding the ground. This would have made the optimal strategy to hug the boss to get free hits in. This led to uninteresting gameplay where the player never needed to move around the room. To disincentivize this strategy, I added jump damage and added a particle effect to signify the damage to the ground. This incentivizes players to move around the room and inevitably leave dodged traps to accumulate.
Space in the arena is important here. I kept the arena tight to make it so the arena would slowly fill with bombs. The player would be crowded if they were trying to save the potions that are spread around the room. As the fight goes on more space becomes available as potions are used, but eventually, the platform becomes crowded. Players may try to ‘drag’ the boss through the bombs and if they do they’ll see the boss will blow them up and take damage. This is designed to be a kiss/curse mechanic and can be an alternative win condition to the fight.
Pressure Plate Puzzle
When a player exits the first gauntlet of enemies, they may notice a gate and a mysterious switch, behind the gate is a glowing ax. I used this as an incentive to get the player to enter the room without thinking too much about how they would get out. This gave the design space to create a pressure plate puzzle. The distance of the inner plate is tuned so a player walking would not be able to get out. The player must use the sprint mechanic to escape. This mechanic could be used to tutorialize the sprint mechanic given its simplicity.
Level Design
The placement of the first coin is directly in the aggro radius of the first spider. This forces the player into a fight that’s seemingly instigated by the spider. This lets the player know this game is about action combat and not stealth or chatting with the enemies. I consider this a way of nonverbally communicating information to the player in the same way that the first goomba in Mario 1-1 is placed just so you will jump on it as you hit the “?” block.
Feedback
While playtesting the game, coins were just accumulated with no purpose. Players didn’t understand their point. I changed the indicator from “Current Coins Collected” to be “Current Coins/Total Coins” to incite exploration and completionism. This caused players to explore and find the hidden room with the pressure plate puzzle when they had 6/7 coins accumulated. This small change shifted players’ perspectives on the coin mechanic from pointless to motivating.
Another issue while playtesting is that players weren’t able to figure out how to pick up the weapons and would try to complete the level without one. I added a small UI indicator to let them know when an interactable object is close enough to pick up.
Final Thoughts
If you’d like to play castle siege you can download it here:
If you’d like to see the code from the game, this is viewable here.