Overview
Dream Ability System (DAS) is an Unreal Engine 5 plugin aimed at allowing the creation of a multitude of abilities and combos. This system was made to be fully online compatible and easy to use.
This plugin was made for Unreal Engine 5
It will be available soon.
How the system works
The system is based on Unreal's Gameplay Ability System. We wanted something similar, but more simple and easier to use. The system relies on Gameplay Tags to handle states and triggers. Our system requires the use of a DASCharacter, a character capable of using and be targeted by abilities. These characters contain an Ability Controller and an Attribute Manager. As the name could suggest, one manages a character's owned abilities and the other, a character's attributes. The Ability controller is responsible of testing if an ability can be used. If the test allows it, this ability is triggered.
MyPart
For the ability manager, I had to come up with something that would allow the use of multiple different abilities. It also had to take into consideration the possibility of elements blocking those abilities and had to allow abilities to be chained to make a combo. I came up with a controller that utilizes gameplay tags in order to control both a character's state, and the abilities.
Ability container
As mentioned, a way to utilize multiple abilities was needed, which caused some problems. The main being that characters did not have the same number or type of abilities. A character could hold movement abilities while another could use a melee ability, and a third could be using both. A way to know which ability was needed to trigger was required. The way I handled it was by matching bound abilities to a gameplay tag (ex : ability.attack.melee). The ability controller then only needed to know which tag the character wanted to use. In the binding of the input, we can then tell the controller to use the ability bound with a specific tag. This way, a character's abilities are not restricted by numbers or types.
Trigger Verification
In order to make sure an ability is not used when it should not be (ex: two at the same time or when the player in in a restricted state), I needed to make a way to verify if an ability could be triggered. The way it was done was partly implemented within the abilities themselves. An ability holds a list of tags that could block it's triggering, as well as another list of tags that are required for it to be used. The ability controller takes those lists and verify if the tags matches with the character's currently applied tags. If a blocking tag is found, or if a required tag is missing, the ability will not be blocked. Once an ability is triggered, it also contains a list of tags to apply to it's owning character. This way, we can block abilities according to what is currently in use. This verification allows us to block or allow abilities according to the character's situation, as well as allowing certain abilities to be used in specific moments.
Ability handling
Since we use multiple abilities and allow characters to use them whenever they want, it was possible for a character to start an ability and enter a state where this ability was no longer possible to use. Since a character could also use multiple abilities at the same time, having multiple abilities blocked while they were already triggered was possible. In order to avoid having this problem impact our system, I added a list of currently active abilities. This list allowed the ability controller to quickly know which ability was still in an active state. As an ability is triggered, it is added to the list. I also bounded an event to the ending of the ability so the controller can remove it from the currently actives once the ability is finished. With this list, it was easy to add functions to cancel either specific abilities, or all of the currently active ones.
Combo system
The combo system caused a bit of confusion. The same key needed to trigger multiple abilities in a specific order. Our system did not have a way to bind multiple abilities to a single input. The way I managed to allow this was by adding a fallback tag to abilities. This fallback tag points to another ability slot in the ability controller. Whenever an ability could not be triggered, the controller would try to trigger the ability in the slot specified by the fallback tag. Making it this way not only allowed for the use of combos, but it also allowed the use of abilities in specific settings, like a different attack if the player is in the air, on the ground or in the water.
Blueprint
The abilities themselves had to be easy to create and modify. We wanted abilities to be mostly made in blueprint, allowing a fast way to create multiple of them without having to modify the code. To make this possible, I made most of the functions in the abilities to be Blueprint implementable with a c++ implementation called within them. This way, it is possible for users to quickly create abilities while still handling the core of what an ability does in code.
Online
The system also needed to be fully usable in an online game. To allow this, I made two additional versions of most functions, a server and client implementation (server RPC and Multicast). Using these implementations, the client also has a bit of prediction when it comes to his own abilities. A server-side test needs to be done to allow a client to use an ability, but the client can still have a visual feedback before we have the server confirmation. This is to have a shorter visual delay between the server and the client. This way, the system could be fully functional in an online environment
Ability life cycle
In order to be usable with multiple other abilities, a life cycle was needed. This is why I made abilities to be divided in parts : the trigger, the feedback and the post-trigger.
The trigger handles the logic. Before the core of the ability is started, it adds tags to it's owning player according to the specified tags to add, as well as pay any attribute price it may have. This is done on the client side to allow prediction. Once these steps are done, the server will be notified and the feedback of the ability will be called.
The feedback handles anything related to giving the player a feedback of the ability. A major part of this feedback is implemented in blueprint since not all abilities has the same feedback. During the implementation of some abilities, it came to our attention that almost all abilities had a sound to be played when it was triggered. With this in mind, I implemented a trigger sound in the C++ implementation of the class.
The post-trigger is defined by either a success (ability completed) or a failure (ability canceled). It is also divided in two parts : The effect of the post-trigger and the feedback it might have. The way an ability is stopped dictates which ending it will have, but in both cases a conclusion of the ability was required. This is why I made a Complete and a Cancel function. They both remove the tags that were applied during the trigger. The only difference is which feedback is called (Complete Feedback or Canceled Feedback).
Credit
Programmers
Alexandre Tremblay
Alexandre Laroche