Hi everyone
The Context:
I’m studying the Gameplay Ability System (GAS) more closely these days along with replicated movement abilities. I never did a multiplayer project in Unreal Engine and after investigation, I’ve found that there are several ways to implement the same feature and I want to know what’s best. I will be using the Gameplay Ability System and the Enhanced Input.
The Question:
Where would the implementation of movement gameplay abilities, such as sprinting, wall running, climbing, sliding, etc be best between the Character Movement Component and the Gameplay Abilities? Would it be both?
My reasoning:
I know that blueprints aren’t ideal for replicated movement mechanics. As such, I always saw that sprint functionality (for example) was always better to be implemented directly into the character movement component. In doing so, you can change the movement speed and acceleration by using different values instead of editing them at run time. However, the Lyra game sample confused me.
In Lyra, there is no sprinting ability by default, but the aim down sight ability does alter the Character Movement Component. I don’t think it does it in an ideal way either. When initiating the ADS ability, the Gameplay Ability itself (not a Gameplay Effect) casts to the Character Movement Component to locally save the character’s walking speed at the moment of triggering the ability, sets a new value, then when the ability ends, it sets back the value to the recorded value. I see here that it is possible to have a Gameplay Ability to have the character sprint, but I see a red flag here:
- Aiming Down Sight is the only thing in the Lyra game sample that I could find that alters the character’s movement. As such, Epic didn’t appear to have implemented the functionality the best way it could have. I see a potential for bugs here. An example of a bug that jumped to my eyes is what happens if you have another speed-altering ability trigger while the character is Aiming Down Sight. These two abilities would take the character movement speed modified by the other abilities as if it was a default value, causing the wrong speed to be applied when these abilities end.
Attribute Sets could be used to track base movement values such as default walking speed and acceleration. When doing so, we would need to modify the character movement component to draw the attributes’ value from the attribute set instead of taking directly from within his own variable. Doing so sounds like a good idea, especially when considering that Gameplay Effects can be stacked together and used to calculate the movement speed with all modifiers associated with it without ever modifying the base value. However, I don’t like this because, from my understanding, it requires the Character Movement Component to continuously draw information from the Attribute Set (and the Gameplay Effects that modifies it) to know how to behave properly rather than simply using the value that it already included by default. For this, I’ve found two methods, but I don’t know which one would be the best.
- The first method is to update the Character Movement Component to include his own array of mathematical modifiers and have the Gameplay Abilities add or remove the modifiers whenever starting and ending an ability.
- The second method would be to check when creating the Character Movement Component if his component owner (the character) also possesses a specified Attribute Set that would include the attribute that would replace the default built-in variable. If found, the Character Movement Component saves a reference which is then used to draw information from the Attribute Set instead of casting to it each time.
If you apply multiple speed buffs, for example, that cumulate together, where is the best place to set the maximum cumulated speed? For example, a base speed of 600u + 2 bonus of 300, but you want a maximum of 1000u in speed.
Beyond the manipulation of value, I also ask myself about permissions, players’ inputs, and settings parameters. For permission, Gameplay Tags are a good source of information that can be used to know, for example, if the character is allowed to sprint in the first place. Using these Gameplay Tags would require the Character Movement Component to also cast to the Gameplay Ability Component to get the relevant information, but I don’t think we want a periodic check like with the speed and acceleration attributes. As such, I’ve come up with two ideas to potentially work around this.
- The first idea is to have the Gameplay Ability Component run a check whenever a related Gameplay Tag changes in quantity. For example, uncrouch a character and set the “Can Crouch” variable to false of his Character Movement Component whenever it gains 1 or more “no crouch” Gameplay Tags, and revert that change whenever it loose the last of those tags. I don’t know if that’s a feasible thing, however.
- The second idea would be to substitute the use of Gameplay Tags for simple flags in the Character Movement Component, one for each movement ability. We could use these flags like the Character Movement Component already use them when wanting to uncrouch. Simply counting the quantity of “this character cannot sprint” to prevent sprinting as a gameplay tag would.
- The problem with this is that if you want to also prevent any abilities that involve sprinting, like a charge ability or something, would still need to use Gameplay Tags to prevent that ability from being used while the character cannot completely execute the ability. Because of this, I think mixing both ideas would be good. Having the Gameplay Ability Component still pushes a set quantity of flags whenever (and only when) the associated Gameplay Tag changes, which is better I think than having the Character Movement Component continuously check for the tag itself.
When thinking of input, a common thing to pay attention to is what direction the player wants to sprint toward versus what direction the character is allowed to sprint toward. If you’re using a Gameplay Ability to make the character sprint by updating the Character movement Component, you’ll also need that ability to monitor the inputs to see if the player wants to sprint in a direction that is not desired. This would make the Gameplay Ability monitor inputs already recorded by the Character Movement Component and change the speed values each time a change of eligibility occurs. When considering this, using Gameplay Ability may be less than optimal. I’m also aware that Gameplay Ability can listen from input cues triggered by the Enhanced Input to trigger an ability, but I’m not sure if that’s really relevant here since we still want to avoid using multiple time the same inputs.
We can also take into account the player’s setting. In some games, a setting can cause the character to sprint by default, making your character sprint whenever allowed to as long as you’re not trying to do a conflicting action and your input is important enough (like pushing a joystick past 90% forward).
I remained focused on the sprint ability so far. That’s because it’s somewhat simple to grasp, but I also wonder the same for other movement abilities like climbing walls and over ledges, wall-running, physic-based sliding, etc. In those contexts, the use of the character capsule component is crucial. For example, climbing a wall requires the character to collide with the wall surface, which can be detected with a simple hit detection like the Character Movement Component already does to get the floor walkable angles. As such, I think this kind of movement feature would be best inside the Character Movement Component to minimize.
Despite all of this, even if I believe that implementing the core movement ability is best made in the Character Movement Component, I still find somewhere that I struggle to find an answer. Let’s suppose the following context. In a game, the player can customize his character with a movement option. As such, the player may have the ability to wall run (horizontal movement along a wall in a given direction) or crawl on walls like a spider can walk on a wall in any direction it desires. Although those are two abilities that are chosen when creating a character, what kind of implementation would be best?
- The first option I see is to create multiple Character Movement Components with each a different mechanic and give the correct one to the player’s character. This would prevent a character from toggling between the two abilities without being able to do a hot swap of movement components at run time, which I don’t think it’s advisable given the physic simulation, replication, etc.
- A second option is to have both movement mechanics within the same Character movement Component and have another set of checks to see which movement method should be used. That would make the toggle between the two more easy on the system, but require an extra check and sets of conditions.
- A third option would be to implement everything into Gameplay Abilities, but as mentioned before, we would need a lot of outside information to be passed over those abilities despite already being recorded elsewhere.
In the end, I do believe that implementing these movement abilities is made in a mixture of both components. The codes that run, trigger, and allow replication should be in the movement Component and the permission in both the Movement Component (to know if a character does something in the first place) and the Gameplay Tags (to know if anything prevents the character from doing something). Despite that, I feel like I’m missing something, probably due to never having done anything that complex with both the Gameplay Ability System and modifying the Character Movement Component. What do you think?