Open GambaCodes opened 3 years ago
Hey, thank you.
I've heard of the evaluation channels before but have never used them. I don't want to include them without a working example.
Then you can do Attribute MyChannel01Mod MyChannel02Mod. Or even Attribute MyChannel01Mod (MyChannel02Mod1 + MyChannel02Mod2).
Where does that happen?
Excellent was looking for something like this, didn't realize it was a feature that was just hidden by default.
The description in those release notes is really helpful, quoting that here just because it was buried a bit:
New: Introduced the concept of "evaluation channels" to non-instant gameplay effects within the ability system! Evaluation channels enable game-specific control over the order in which modifiers are evaluated in attribute calculations.
A game may specify how many channels it would like to use, as well as what they are named, and then modifiers can specify which channel they work on. The channels are evaluated in order, with the numerical output of the first channel serving as the input to the second channel, and so on.
Example: Imagine a sample attribute with a base value of 100. Now apply a multiplicative mod with magnitude 1.1 in channel 0 and a multiplicative mod with magnitude 1.1 in channel 1. The result will evaluate as ((100 1.1) 1.1) instead of (100 * 1.2).
To use channels in a game, two settings within the INI section for AbilitySystemGlobals must be configured. First, bAllowGameplayModEvaluationChannels must be set to true, and second, the channels that should be used (and their names) must be specified in GameplayModEvaluationChannelAliases. Additionally, a game can optionally specify a default channel to use via DefaultGameplayModEvaluationChannel.
In addition, added various new channel-related functionality to the ability classes' API, such as the ability to base the magnitude of a modifier off of an attribute only evaluated up to a certain channel.
And here's some more important snippets from source after reading into them more:
Each channel gets evaluated in order, with the final result from the previous channel used as the base value for the next channel. This happens in FAggregatorModChannelContainer::EvaluateWithBase
:
float FAggregatorModChannelContainer::EvaluateWithBase(float InlineBaseValue, const FAggregatorEvaluateParameters& Parameters) const
{
float ComputedValue = InlineBaseValue;
for (auto& ChannelEntry : ModChannelsMap)
{
const FAggregatorModChannel& CurChannel = ChannelEntry.Value;
ComputedValue = CurChannel.EvaluateWithBase(ComputedValue, Parameters);
}
return ComputedValue;
}
Note that although it's iterating a map, the order of the map is automatically managed in FAggregatorModChannelContainer::FindOrAddModChannel
, to make sure that the channels are always evaluated in order:
FAggregatorModChannel& FAggregatorModChannelContainer::FindOrAddModChannel(EGameplayModEvaluationChannel Channel)
{
FAggregatorModChannel* FoundChannel = ModChannelsMap.Find(Channel);
if (!FoundChannel)
{
// Adding a new channel, need to resort the map to preserve key order for evaluation
ModChannelsMap.Add(Channel);
ModChannelsMap.KeySort(TLess<EGameplayModEvaluationChannel>());
FoundChannel = ModChannelsMap.Find(Channel);
}
check(FoundChannel);
return *FoundChannel;
}
Here's a practical example in which a character's move speed is being overridden by a Run ability, and then multiplied afterwards to apply a Slow debuff:
GE_Run
sets the attribute to exactly 650
GE_Slowed
multiplies the attribute by 0.25
Since all modifiers in Channel0
are fully evaluated before any modifiers in Channel1
, the Override modifier op can be used here while still allowing Add or Multiply operations afterwards by putting them in a higher channel.
One last visual representation of how a subset of the modifier operations within each channel are used for the above example, with 350 as an arbitrary base value:
Thanks again for this great resource 🙏🏼
This is really useful and great! I was about to start looking into how to modify EvaluateWithBase and really didn't want to dig into engine code to make a simple change. That fixes what I thought was a GAS shortcoming perfectly!
At the end of the section it's suggested that devs change engine code if they want their modifiers to be multiplied or divided instead of being added before the operation. While researching this issue, I ran into the concept of evaluation channels that were added in 4.14.
All you need to do is add the section below to DefaultGame.ini and then you can keep the original behavior and multiple or divide channels together.
[/Script/GameplayAbilities.AbilitySystemGlobals] bAllowGameplayModEvaluationChannels=true GameplayModEvaluationChannelAliases[0]="MyChannel01" GameplayModEvaluationChannelAliases[1]="MyChannel02"
There are 10 channels defined in GameplayEffectTypes.h (EGameplayModEvaluationChannel), and for each channel you give a name to in the ini, you'll get to select that channel in the gameplay effect.
Then you can do Attribute MyChannel01Mod MyChannel02Mod. Or even Attribute MyChannel01Mod (MyChannel02Mod1 + MyChannel02Mod2).
Since a lot of people rely on this documentation, which is great btw, I thought I'd suggest an alternate solution.