#Tags based movement speed modifier with mover
1 messages ยท Page 1 of 1 (latest)
so
here is what ive done so far
ive tested this with my movementstate based ability(walk, run,sprint) and and right now, its working ish with i handle the calculation inside my executioncalculation and use that movementspeed attribute and calculate that with modifier
this my my based charactermovementstateability
here my sprint ability that use that parent class
now for sprint, havent get it to fully working yet as inputhold type ability, i need to feed into movermodifier but that can be take care later
here my walkrun ability which great for this tagsbased solution
and here is where the attribute is calculated
here my executions
and that the attribute is set in my characterattributeset
damn i cannot forwards exisitng message into a thread :/
so from what i found with what i do now is if i apply the ability that apply the charactermovementstate ability, it will apply loose tags that my executioncalc will listen to
based on that, it will interate and get the multiplier to adjust the movementspeed attribute
and then in postgameplayeffectexecute in characterattributeset, on movementspeedattribute we will apply to movercommonlegacysettings maxspeed and acceleration to adjust the playerspeed
PROBLEMS:
input hold based ability wont work as attribute is applied ONCE even though input havent been released yet
previously, i use mover movement modifier and it will continuosly apply the modfiier UNTIL i inputreleased and end the ability there which clear up the handle and eveyrthing
here how it done previously
now my current solution is based on kaos dmage resistance blog
For State-Based Movement (Walk/Run):
- Use GAS attributes with execution calculations (your current approach)
- Apply permanent/duration-based GameplayEffects
For Input-Hold Movement (Sprint):
- Use Mover movement modifiers for continuous application
- Apply loose tags via GameplayEffects for the modifier to read
// MovementSpeedExecutionCalculation.h
UCLASS()
class UMovementSpeedExecutionCalculation : public UGameplayEffectExecutionCalculation
{
GENERATED_BODY()
public:
UMovementSpeedExecutionCalculation();
virtual void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, OUT FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const override;
private:
FGameplayEffectAttributeCaptureDefinition MovementSpeedDef;
};
// MovementSpeedExecutionCalculation.cpp
void UMovementSpeedExecutionCalculation::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, OUT FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
const FGameplayTagContainer* SourceTags = ExecutionParams.GetSourceTags();
const FGameplayTagContainer* TargetTags = ExecutionParams.GetTargetTags();
FAggregatorEvaluateParameters EvaluateParameters;
EvaluateParameters.SourceTags = SourceTags;
EvaluateParameters.TargetTags = TargetTags;
float BaseMovementSpeed = 0.0f;
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(MovementSpeedDef, EvaluateParameters, BaseMovementSpeed);
// Calculate multiplier based on movement state tags
float MovementMultiplier = 1.0f;
if (TargetTags->HasTagExact(FGameplayTag::RequestGameplayTag(TEXT("MovementState.Walk"))))
{
MovementMultiplier = 0.5f;
}
else if (TargetTags->HasTagExact(FGameplayTag::RequestGameplayTag(TEXT("MovementState.Run"))))
{
MovementMultiplier = 1.0f;
}
float FinalMovementSpeed = BaseMovementSpeed * MovementMultiplier;
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UYourAttributeSet::GetMovementSpeedAttribute(), EGameplayModOp::Override, FinalMovementSpeed));
}
// SprintMovementModifier.h
UCLASS()
class USprintMovementModifier : public UBaseMovementModifier
{
GENERATED_BODY()
public:
virtual bool OnGenerateMove(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FProposedMove& OutProposedMove) const override;
virtual void OnSimulationTick(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FMoverTickEndData& OutputState) const override;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float SprintMultiplier = 2.0f;
private:
bool ShouldApplySprintModifier(const FMoverTickStartData& StartState) const;
};
// SprintMovementModifier.cpp
bool USprintMovementModifier::OnGenerateMove(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FProposedMove& OutProposedMove) const
{
if (!ShouldApplySprintModifier(StartState))
{
return false;
}
// Apply sprint speed modification
OutProposedMove.LinearVelocity *= SprintMultiplier;
return true;
}
bool USprintMovementModifier::ShouldApplySprintModifier(const FMoverTickStartData& StartState) const
{
// Check for sprint tags from GAS
if (const APawn* Pawn = StartState.MovementComponent->GetPawnOwner())
{
if (const IAbilitySystemInterface* ASI = Cast<IAbilitySystemInterface>(Pawn))
{
if (UAbilitySystemComponent* ASC = ASI->GetAbilitySystemComponent())
{
return ASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag(TEXT("MovementState.Sprint")));
}
}
}
return false;
}
GameplayEffect Setup:
- Create a SprintTagEffect (Duration-based):
- Duration Policy: Has Duration
- Duration Magnitude: Infinite (or very long)
- Granted Tags:
MovementState.Sprint - No attribute modifiers needed - the modifier reads the tag directly
Why not simply use an abiity and its "WaitInputRelease" node ? Or does that not work with Mover?
i have my sprint that way and it works
im cmc though
also @opal comet Sry for the ping, was just wondering, one can apply exec calcs directly to attributes? Or what did you mean by "using gas attributes with exec calcs) , dont we need a GE in order to have exec calcs modify that?
(unrelated to his issue)
This is mentioned within the Kaos tutorial iirc. The gameplay calculation is indeed within the gameplay effect only reason to have it is to avoid having multiple gameplay effects and gameplay abilities when we only need to have 1 for something like walk, run etc.
Oh okay so just use them as regular intended gas way
reading through the gameplay ability that is attached below notes the gameplay effect that is added ๐
pretty much ๐
@opal comet @wide cradle @primal delta so yesterday and today i sat down and rethink this from scratch.
i was thinking, how about i always make this modfiier ALWAYS active and we never need to remove them and it will ONLY listen to any gameplaytag added and if that tag is added, do the calculation.
this is without GAS and purely mover.
this is a bit working but right now, having problem with registering the tag and adjusting the mover movementspeed based on the tag. the idea is still the same from previous example implementation i gave using GAS
this way, the modfiier ONLY need to listen to any tag added and do the calculation inside it and encapsulate the behaviour to outside GAS.
here my current atempt
im using a component rn to keep track of these tags changes
still W.I.P
tbh i think i am overcomplicated this as ive been working on this since last week
tbh i think i am at the point where i have no idea what the best approach to go. i would love to merge all of this solution together
thats enough rambling for today
prob will try again tomorrow with a fresh mind
Using an exec seems such a bad idea
Exec won't be predicted at all, so you'll end up with frequent desync
Excellent point, could use a ability task then to aid in the sync / prediction
if its just for tags, just local determination on both client and server is enough
ah i forgot to mention, my game is single plaer so that wont be an issue
alright ๐
@primal delta hey again, so an update, finally have a working 1.0 version of this modfiier ๐
now have to figure out the horrible tagrelationship that have in each ability right now using tagrelationshipmapping
dang took me another day to built it from scratch, finnaly found the middle ground that i like that combine mover movementmodifier and GAS