top of page
Tomb of Alar
About
Tomb of Alar is a top down action shooter game where you play as Lich. You progress through the corridors of the tomb slaying creatures that are trying to stop you. You use your magic abilities to fight the back.
Project Info
-
Role: AI, Gameplay and Animation Programmer,
-
Time: 4 Weeks
-
Team Size: 8
-
Engine: Unreal Engine
-
Engine Experience: 7 months
-
Programming Experience: 1 year & 10 months
Background
We decided early on that we are going to do top down game. The reasons for that was that we didn't have anyone who would be excited to work with cameras which are more work in non top-down games and also we didn't have animators who'd make animations. It is more forgiving when you have janky animations in top down. In other words we played with our strengths.
During the project I managed to create AI that I can be proud of, I implemented animations that look nice and blend well between each other. I created sophisticated and flexible spawners for my designers to use. In addition to that I reworked our Attack input system to accomadate animations.
Rats
Challenges
​The purpose for rats was to swarm and surround the player. Even though, Unreal engine has built-it navigation system, it wasn't enough to make the swarm mechanic.
The challenge was to make them surround the player and spread out rather than moving in a straight line (which is the fastest way to get to the target).
Result
How I solved swarming problems
Problems
-
The rats chase the player in a straight line.
-
The rats do not surround the player.
-
Get stuck among each other.
Steering behaviour
In order to solve the problems I implemented a streeing behaviour - Separation force. Basically, it pushes rats away from each. The closer the rat to other rats the stronger it is pushed.
I would get a vector from that behaviour, then I'd combine it with the Direction to the player vector.
Unfortunately that caused some problems e.g. if the player and two rats were on the same line the furthest rat would get stuck because it was pushed forward (towards the player) and backwards (Away from the rat) at the same time.
To minigate that, I added additional parameters (Angle threshold) which would prevent adding the separation force.
The last piece of the puzzle was to implement a parameter that makes sure the rats aren't pushed away as they get close to the player. I called the parameter "Weight" which solved that problem. The way it works is that as the rats reach certain distance to the player they get less and less affected by separation force
Behaviour Tree
-
LookAtTarget - Rotates the rat towards the player.
-
SeparationForce - explained above.
-
CombineVectors - Sums separation force, Direction to the player and Current Location.
Debugging
Debugging AI is extremely important. I heard some people call their AI's "children", however I call them "my disappointments" because that's what they do...
Direction received from Separation Force
Green sphere - Personal Space - Radius within which it can be pushed by other rats.
White sphere - Weight - The closer the rat to the center of the sphere the less it is affected by separation force.
Acceptance angle - filters angle for Separation Force
AI - Attack
-
Attack is triggered by an AnimationBasedTask called PerformAttack. The task simply calls an interface function (PerformAttack) which simply plays an animation.
-
Animations have animNotifies that call interface functions.
-
Then Main class (EnemyBase) starts a timer that is perfroming Sphere Traces to detect hits.
-
Red sphere traces visualization
Animation Implementation
Contribution
-
Retargetting animations
-
Cutting Animations
-
Strafing
-
Layering Animations
Retargetting
I used different assets to get animations from
Cutting\Editting
I had to adapt the animation to the responsive input my designers wanted to have. I worked with blending and transitioning animations.
Strafing
Gameplay
Challenge
I had to rework how our input functions when we added animations. It was a heavy task since the game had been programmed to perform attacks straight from the input without considering animations. The game was supposed to be responsive and not jerky.
The Attack input is Left and Right buttons, the player can switch between them incredibly fast. Animations had to be adjusted a lot.
The goal was to make fast and smooth transitions between animations and responsive input.
Result
Tools - Enemy spawner
The goal
The biggest tool I made for my designers was the enemy spawner. My personal goal was to make the enemy spawner that supports a lot of mechanics. I talked to my designers to get the feeling of what the'd need, but I wanted to be very flexible to make new ideas come true as well.
In other words, I made a sophisticated enemy spawner that is flexible and I tried to make it easy to use.
How to use it
To trigger a spawner I made a simple (blueprint accessible) function.
The spawner can spawn automatically (with intervals, e.g. if you hit a collider start the waves) or be controlled manually (e.g. spawn next wave when all enemies from the previous are killed).
Spawner Capabilties
-
It can spawn enemies at the start of the game.
-
It can spawn waves of enemies (both one at a time or in chunks)
-
It can spawn multiple types of enemies or single type
-
The spawner visualizes the positions of the spawns.
-
The spawner hides irrelevant parameters (e.g. if you spawn a single enemy desginers cannot see any lists)
​
The spawner has few settings, but it can be played with to achieve desired goals.
Example
I'm not going to explain how everything works as it's going to take a long time. However, I will show you an example. I'll show you how to set the spawner so that it will create three waves of enemies when the player gets close.
Desired goal - 3 waves, start when reached the box trigger.
-
1st wave - 5 rats
-
2nd wave - 4 rats and a skeleton
-
3rd wave - 5 skeletons
Takeaway
In this project I sharpened my AI programming skills. I practiced using behaviour trees and implemented controllers in a better way. I stumbled upon a biggest question with AI and Animations. How do I make them independent, but also communicate between each other. AI is required to know about the state of the animations to have the flow of the tasks. I was wondering a lot about that question and I found a smart solution in my next project (Combat system).
Another big realization was the parameters. In the project, to change the health of a certain enemy you need to go into his blueprint. It might not sound too bad, but you need to consider that you're working in a team and someone else might be working with that enemy. Also as a designer you're not tunning only one health parameter, you're tunning all of them. There I realised that it's better to put such variables in a DataTable and the enemies can grab them rather than having them from the beginning.
My team
Designers:
Mathias Sandström
Savelij Ognev
Elias Bernmarker
Tove Carlund
William Chung
Programmers:
Leo Wahlund
Markis Wikström
bottom of page

