Note this is a similar question to -> Mover - running simulation on any thread issues
But not the same (as I am using Async movement modes, unlike in the question above)
I am evaluating the Mover Component for our character.
I’ve started with the basic CharacterMoverComponent as I couldn’t get the Physics based mover working in 5.7 Examples (the character would not move at all).
I’ve got the character working, and I wanted to evaulate the Async movement modes to see if we can use those at all.
So I swapped out the Walking, Falling & Flying modes for UAsyncFallingMode, UAsyncFlyingMode & UAsyncWalkingMode.
So far so good, but that doesn’t make them Async as they appear to need a different Liason to do that.
I then made my own Liason, that enables Async ticking.
- First problem is, I can’t call SetUseAsyncMovementSimulationTick() because it will not actually turn on Async movement as there is a global that forces it to be off? Not sure why that is useful? So I’ve had to copy the function bodies out into the constructor of my Liason (constructor and method pasted below) and remove the reference to the global/cvar.
UUMoverStandaloneLiaisonAsyncComponent::UUMoverStandaloneLiaisonAsyncComponent()
{
// NOTE: Not calling \#SetUseAsyncProduceInput \& SetUseAsyncMovementSimulationTick because
// they check a global CVar and disable the async by default? Not sure why Async is all off by default and
// requires a CVar command to turn on?
bUseAsyncProduceInput \= true;
ProduceInputTickFunction.bRunOnAnyThread \= bUseAsyncProduceInput;
bUseAsyncMovementSimulationTick \= true;
SimulateMovementTickFunction.bRunOnAnyThread \= bUseAsyncMovementSimulationTick;
}
bool UUMoverStandaloneLiaisonAsyncComponent::IsAsync() const
{
return true;
}
- Next problem, is the mover then complains that the movement modes are NOT async during data validation, so despite being called UAsyncFallingMode etc, they are marked as Async = false by default, so I had to go in and change all the mode to be async on each mode in the data on the character.
- So after that, I can run the game and I drop a few characters into a level to see what they will do. Pretty much instantly crashes at this point, the call stack is below.
It looks like the Mover is attempting to turn the component tick back on for the Mover, because the character now has a movement base and it wants a new tick to enable a tick pre-requisite? so the mover can get ticked before the base? (see callstack in the repro steps).
----
It’s crashing trying to remove the tick function, and it looks like it’s access a global data structure of ticks for the level?
if (bInEnabled == (TickState == ETickState::Disabled))
{
FTickTaskLevel\* TickTaskLevel \= InternalData\-\>TickTaskLevel;
check(TickTaskLevel);
TickTaskLevel\-\>RemoveTickFunction(this);
-----
So my question is? Is what I am doing a valid setup? or is this just not possible? And if so, can you setup a character with kinematic movement that actually works async?
Seems like if I am a kinematic mover and I go Async, then I’m always going to hit problems with this code below, which ends up running on worker threads.
And the linked question also said that MotionWarping isn’t compatible, so is that still the case? as then async might be a non-starter for us anyway, as we have too much to rely on that feature to give it up.
if (bSupportsKinematicBasedMovement)
{
UpdateBasedMovementScheduling(SimOutput);
}
----
Many Thanks
Dave