Aura



Project Info

  • Role: Solo Developer
  • Team Size: 1
  • Time Frame: Jan 2025 - Present (In Progress)
  • Engine: Unreal Engine 5

About

Aura is a top-down RPG built using Unreal Engine's Gameplay Ability System (GAS). Designed primarily for a solo player experience, it also supports multiplayer functionality. Players control Aura, casting spells, battling enemies, and leveling up attributes and skills to grow stronger. This project extensively utilizes Gameplay Effects, Gameplay Tags, Gameplay Attributes, Gameplay Cues, and all core aspects of GAS. I developed Aura by following an online course with over 100 hours of video content, applying what I learned to create a fully functional RPG system.

Source Code: GitHub Repository
Course: Course Link



Combat (Projectiles)

Currently, the project features one implemented attack spell: the fireball. This spell is built upon a custom projectile parent class that I developed, which itself inherits from a gameplay ability parent class. The fireball follows Unreal Engine’s Gameplay Ability System (GAS) structure, ensuring modularity and scalability for future abilities.

The SpawnProjectile function is responsible for spawning projectiles while ensuring execution only occurs on the server by checking for authority. It determines the spawn location via the combat interface, calculates the appropriate rotation toward the target, and applies an optional pitch override if specified. A transform is then created using these values, and the projectile is spawned using SpawnActorDeferred< AAuraProjectile >(), allowing modifications before finalization.

Once the projectile is instantiated, a gameplay effect context is created using the ability system component, linking it to the ability and projectile. Relevant hit results and source objects are added for tracking, and an outgoing gameplay effect spec is generated to define the damage properties. The function then iterates through DamageTypes, scaling damage values based on the ability level and assigning them accordingly. Finally, the projectile stores this effect spec handle and completes its spawn process via FinishSpawning().


SpawnProjectile is then called in a Gameplay Ability blueprint class where the firing animation montage and projectile location are passed in.

Enemies and AI

All the enemies in the project use the same behavioral tree and blackboard. The tree first calls the FindNearestPlayer function, a blueprint class inheriting from BTService Blueprint Base. FindNearestPlayer gets the distance from the controlled pawn, Aura, and the other actor, the enemy, using GetDistanceTo. It then calculates the distance and determines if the two actors are close enough and the enemies can “see” Aura. The blackboard values are set are passed to the behavior tree to make the decision of whether to go to Aura.

The behavior tree then checks if the enemy is alive, if the enemy has a target, and if the enemy is hit reacting. If these checks pass the selector checks whether the enemy is a ranged attacker, melee attacker and the distance to Aura. If an enemy is a Melee attacker then the distance to attack will be less than that of a ranged attacker. The selector knows what type of attacker an enemy is by checking its Gameplay Tag set on the enemies blueprint.

Enemies and AI (Shaman)

The Shaman is an old wizard type character that can spawn Minions and shoot fireballs. The fire step in creating the Minion spawning ability was finding the spawn locations.

The first step was finding locations to spawn the Minions with the GetSpawnLocations function. The function calculates the spawn locations by first determining the character's forward direction and location. It then spreads the spawn points evenly within a defined area, considering the number of minions to spawn and the spread distance. The function uses RotateAngleAxis to calculate the position of each spawn within the specified spread area. For each potential spawn location, the function performs a line trace to ensure that the spot is not blocked by any obstacles. If an obstruction is detected, it adjusts the spawn point to the point of impact.

The function returns an array of FVector values representing the valid spawn locations for the minions, which can then be used to spawn the minions at those positions. Additionally, the GetRandomMinionClass function randomly selects a minion class from a predefined list, allowing for diverse types of minions to be summoned during gameplay.

After implementing GetSpawnLocations in C++, the remainder of the ability was completed in a Gameplay Ability Blueprint class. First, GetSpawnLocations is called, returning an array of valid spawn locations. For each location, the SpawnSystemAtLocation() function is called to trigger the corresponding Niagara Effect at that position. Then, the summon montage is played, and the SpawnActor() function is executed within a loop, passing each spawn location one at a time.

The minions' rotation is set using LookAtLocation(), ensuring they face the player based on the Shaman's orientation. When all minions have been killed, the number of minions to summon is decremented by one, so the Shaman will summon one less minion each time until no minions are spawned.