Synchronising and updating actor transforms in Mass Entity performance

Hey, we’re looking to use Mass Entity in 5.5.4 and are currently testing how many entities can move around before hitting our frame budget.

Our test consists of 500 entities with the `MassMovableVisualizationTrait` and an actor representation that has a single `CapsuleComponent` as the root, a `SkeletalMeshComponent` and a `MassAgentComponent` with a puppet entity containing only the `AgentCapsuleCollisionSync` trait.

As our 500 entities are navigating, we’re seeing on average of ~3ms being spent in the game thread on the `MassTransformToActorCapsuleTranslator` process, as it’s doing a lot when propagating the updated transform on the component.

This is quite a lot of time for our frame budget, especially since we intend to extend some of the Mass behaviour in StateTree.

We’ve made some optimisations already, such as setting `KinematicBonesUpdateType` to `SkipAllBones` on the `SkeletalMeshComponent`.

We’ve also tried using `UMassCharacterMovementToActorTranslator` and `UMassCharacterOrientationToActorTranslator` instead, but they seem to suffer from the same slowdowns.

We assume that the propagations from updating the transforms can’t really be simplified further, so we were hoping to try and split the process into multiple threads using `ParallelForEachEntityChunk`, but we’re coming across a lot of ensures related to physics.

Refereeing to [this [Content removed] it appears that we can’t have a call to `SetBodyTransform` in anywhere but the game thread.

Are you aware of any work-arounds or strategies we could take to reduce the cost of updating the transforms of 500+ entities in a mass process?

Thank you.

Steps to Reproduce

Hi Ben,

This is indeed an issue of needing to make changes between Mass and Actors that requires game thread access which can become quite expensive. Our approach has been to limit the amount of entities spawned as Actors with ISM representation for further away entities. Is it at all possible to use less complex ISM representation for more of the entities? There has been some work on internal projects using Mass, and I will reach out to some of the team to see any settings or number of Actors being used there as it is targeting 60 FPS.

we were hoping to try and split the process into multiple threads using `ParallelForEachEntityChunk`

In some recent perf testing, we found that parallelizing usually did not become a net positive for performance until over 10k entities. The overhead in setting it up seems to outweigh benefits in the current setup. This was for Mass processors in general, and I do not believe the testing harness included translator processors as we wanted to check perf of Mass and not in the sync points.

-James

Hey James,

It’s a little tough in our situation to switch to ISMs as out game view is top down, with the expectation that there would be a lot of enemies on screen.

So there’s no real concept of LODs, it’s much more like they’re either on the screen or off the screen.

We also need an actor for each agent even when they aren’t on screen, due to each agent needing a GAS component and capsule collision.

A potential strategy we could take would be to use ISMs to represent the capsule collisions when they’re off-screen, then the movements would be batched which should improve transform update performance?

And the GAS components can all be part of a single actor with a `TMap<EntityHandle, AbilitySysComp>` maybe.

We’ll keep investigating further, but yes we would love to hear if the team has came up with any strategies for this bottleneck.

Particularly anything to do with batching the transform updates of multiple actors in a single call that could reduce overhead in Chaos for example.

Cheers,

Ben.

Hey James,

Just to follow up, we’re assessing if the overhead of setting up Mass is worth the performance gains, if we only end up with 200 entities max.

We want the entities to have the same gameplay capabilities as a typical character:

-Capsule Collision with gravity, sliding and typical character physics.

-GAS Ability Sys Component

-Nav Mesh path following

-StateTree AI

We’re implementing our own nav mesh path following through Mass, but to have gravity and capsule/char physics, we’re relying on a MovementSync trait in both directions, which requires the actor puppet to be a Character with a CharacterMovementComponent.

At this point, we’re bypassing the whole point of Mass, especially if we’re restricting ourselves to the GameThread in the movement updates, and we would only be using Mass for path following and State Tree at this point.

We can try and port a lot of the movement physics from the Char Move Comp so that we could hopefully process them all in parallel, but this seems like it might be negligible for 200 entities, especially if the mass process “graph” has some performance overhead.

It would be great to hear from you or the team, if you predict that we won’t be getting much benefiting in porting a lot of the ACharacter/CMC capabilities, when we’re not expecting 1000s of entities.

Cheers,

Ben.

Hi Ben,

My apologies for the delay in getting back to you about this. I will try to address all the questions and points you made. If I miss one, please let me know as it was unintentional.

We’re assessing if the overhead of setting up Mass is worth the performance gains, if we only end up with 200 entities max

I feel that the perf increases from Mass may be negligible for running for only 200 entities. You could look at A/B testing to see what the Mass processor setup overhead would be versus just Actors.

Needing Actors for all entities on screen

Would it be possible to add more LOD levels for representation with Actors where you could use more simplified characters for those far away or near edges of the screen? Mass has Low and High by default but more can be added. This should allow for simplifying the meshes and potentially remove some components.

Gameplay capabilities for each character

There has been some work for making navigation more accessible in Mass with a first, and very experimental/rough, draft that will be available in 5.6. It may be useful to either serve as the basis or aid in setting up your own. There are also community versions who have worked on navmesh navigation for Mass entities. We also have been working on Mass StateTree improvements, as well as StateTree in general, which are in 5.6 and can certainly help with StateTree perf. There are also new features such as being able to specify if a task will be used for considering success of a state.

As for using GAS with Mass, it is something we have held very high-level discussions around integrating. The main issue is the current GAS implementation is built around the `AbilitySystemComponent`. There are issues with needing to track the state of the ASC, effects, abilities, and stats persist between LOD changes since Actor representation changes. It is something we have on our radar since GAS is widely used by licensees and Epic internally. I do not have any timeline on when this may get investigated further, or if we will add integration support for the systems.

With all of that being said, it does look like Actors may be a better fit for your project, but 200 full Characters could be quite the challenge with keeping perf at your desired levels. CMC is a heavy component by itself, and I believe Mover 2.0 is working to make it more lightweight. I do not know the full support of Mover 2.0 currently, but there has been work to support AI pathfollowing which I think will be included for 5.6. To use it, you may need to make a translator and update some of the fragments to support having that component rather than a CMC.

-James

Hey James,

Really appreciate the detailed reply!

Overhead and LODs

We’ve recently done A/B testing for 300 entities, and it seems that the gains from Mass (ST, Path Following) are negated by the MassToActor translators for sure.

We will do further investigations to see if we can simplify the actors or use lower LODs, so that the transform update propagation isn’t as costly.

Gameplay

We’ve synced to 5.6 and are interested to see if similarities between the new Mass Navigation and our own implementation!

GAS w/ Mass

We’re thinking of implementing a central actor that’ll contain all GAS components and map each one to an entity.

Mover 2.0

We’re going to spend the next few days investigating if switching to Mover might give us some performance gains, if not, at least it might be a bit more straight forward to strip down compared to CMC.

The movement seems to be the biggest bottleneck for us now, so if we can solve that then I think we can decide if it’s better to go ahead with Actors instead of Mass.

Cheers,

Ben.

That is good to hear. The Mover translators are included in a separate experimental plugin from Mover and Mass call MoverIntegrations I believe. It contains some other files for integrating Mover with different systems such as animation, Mass, etc. I think this should all be included in 5.6, but if not, it will be available to cherrypick in UE5 main.