Movement with Mass Framework
How to process movement with Mass Framework. Mass Framework is a ECS for managing crowds and traffic in Unreal 5.0 and above.

Processing Movement with MassGameplay built-in resources
Movement Trait
Built-in
MassGameplayTrait located AtUE5/Engine/Plugins/Runtime/MassGameplay/Source/MassMovementImage
.hUCLASS(meta = (DisplayName = "Movement")) class MASSMOVEMENT_API UMassMovementTrait : public UMassEntityTraitBase { GENERATED_BODY() protected: virtual void BuildTemplate(FMassEntityTemplateBuildContext& BuildContext, const UWorld& World) const override; UPROPERTY(Category="Movement", EditAnywhere) FMassMovementParameters Movement; };.cppvoid UMassMovementTrait::BuildTemplate(FMassEntityTemplateBuildContext& BuildContext, const UWorld& World) const { FMassEntityManager& EntityManager = UE::Mass::Utils::GetEntityManagerChecked(World); BuildContext.<mark>RequireFragment<FAgentRadiusFragment></mark>(); BuildContext.<mark>RequireFragment<FTransformFragment></mark>(); BuildContext.<mark>AddFragment<FMassVelocityFragment></mark>(); BuildContext.<mark>AddFragment<FMassForceFragment></mark>(); const FConstSharedStruct MovementFragment = EntityManager.GetOrCreateConstSharedFragment(Movement); BuildContext.AddConstSharedFragment(MovementFragment); }Check Built-in Movement processor to get knwoledge of processing the movement from the trait
Fragments for movement
As you can see, the built-in
Movement TraitofMassGameplayplugin works with the 4 following fragments:FMassVelocityFragmentLocated at
UE5/Engine/Plugins/Runtime/MassGameplay/Source/MassMovementUSTRUCT() struct MASSMOVEMENT_API FMassVelocityFragment : public FMassFragment { GENERATED_BODY() <mark>FVector Value = FVector::ZeroVector;</mark> };FMassForceFragmentLocated at
UE5/Engine/Plugins/Runtime/MassGameplay/Source/MassMovementUSTRUCT() struct MASSMOVEMENT_API FMassForceFragment : public FMassFragment { GENERATED_BODY() <mark>FVector Value = FVector::ZeroVector;</mark> };FAgentRadiusFragmentLocated at
UE5/Engine/Plugins/Runtime/MassGameplay/Source/MassCommonUSTRUCT() struct MASSCOMMON_API FAgentRadiusFragment : public FMassFragment { GENERATED_BODY() UPROPERTY(EditAnywhere, Category = "") <mark>float Radius = 40.f;</mark> };FTransformFragmentLocated at
UE5/Engine/Plugins/Runtime/MassGameplay/Source/MassCommonUSTRUCT() struct MASSCOMMON_API FTransformFragment : public FMassFragment { GENERATED_BODY() const FTransform& GetTransform() const { return Transform; } void SetTransform(const FTransform& InTransform) { Transform = InTransform; } FTransform& GetMutableTransform() { return Transform; } protected: UPROPERTY(Transient) <mark>FTransform Transform;</mark> };Movement Processor
Built-in
MassGameplayProcessor located atUE5/Engine/Plugins/Runtime/MassGameplay/Source/MassMovementNow, as you know the fragments and their values, you can check how they are used for automatical processing of movement. The point is, in a case of using the built-in
Movement Trait(MassGameplay), all you need for processing movements is to set (update) the traits values. You can do that e.g. from a custom Mass processor..hUCLASS() class MASSMOVEMENT_API UMassApplyMovementProcessor : public UMassProcessor { GENERATED_BODY() public: UMassApplyMovementProcessor(); protected: virtual void ConfigureQueries() override; virtual void Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context) override; private: FMassEntityQuery EntityQuery; };.cppUMassApplyMovementProcessor::UMassApplyMovementProcessor() : EntityQuery(*this) { ExecutionFlags = (int32)EProcessorExecutionFlags::All; ExecutionOrder.ExecuteInGroup = UE::Mass::ProcessorGroupNames::Movement; ExecutionOrder.ExecuteAfter.Add(UE::Mass::ProcessorGroupNames::Avoidance); } void UMassApplyMovementProcessor::ConfigureQueries() { EntityQuery.<mark>AddRequirement<FMassVelocityFragment></mark>(EMassFragmentAccess::ReadWrite); EntityQuery.<mark>AddRequirement<FTransformFragment></mark>(EMassFragmentAccess::ReadWrite); EntityQuery.<mark>AddRequirement<FMassForceFragment></mark>(EMassFragmentAccess::ReadWrite); EntityQuery.<mark>AddTagRequirement<FMassOffLODTag></mark>(EMassFragmentPresence::None); EntityQuery.<mark>AddConstSharedRequirement<FMassMovementParameters></mark>(EMassFragmentPresence::All); } void UMassApplyMovementProcessor::Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context) { // Clamp max delta time to avoid force explosion on large time steps (i.e. during initialization). const float DeltaTime = FMath::Min(0.1f, Context.GetDeltaTimeSeconds()); QUICK_SCOPE_CYCLE_COUNTER(HighRes); EntityQuery.ForEachEntityChunk(EntityManager, Context, [this, DeltaTime](FMassExecutionContext& Context) { const int32 NumEntities = Context.GetNumEntities(); const FMassMovementParameters& MovementParams = Context.GetConstSharedFragment<FMassMovementParameters>(); const TArrayView<FTransformFragment> LocationList = Context.GetMutableFragmentView<FTransformFragment>(); const TArrayView<FMassForceFragment> ForceList = Context.GetMutableFragmentView<FMassForceFragment>(); const TArrayView<FMassVelocityFragment> VelocityList = Context.GetMutableFragmentView<FMassVelocityFragment>(); for (int32 EntityIndex = 0; EntityIndex < NumEntities; ++EntityIndex) { FMassForceFragment& Force = ForceList[EntityIndex]; FMassVelocityFragment& Velocity = VelocityList[EntityIndex]; FTransform& CurrentTransform = LocationList[EntityIndex].GetMutableTransform(); // Update velocity from steering forces. (Force default value is ZeroVevtor) <mark>Velocity.Value += Force.Value * DeltaTime;</mark> FVector CurrentLocation = CurrentTransform.GetLocation(); <mark>CurrentLocation += Velocity.Value * DeltaTime;</mark> <mark>CurrentTransform.SetTranslation(CurrentLocation);</mark> } }); }


