ALS-Refactored
ALS-Refactored copied to clipboard
Mantle not sync on Client (Dedicated Server Mode)
https://drive.google.com/file/d/1Xk_nWE79a-kSQeeq2AfOxkLaV2nFx0jD/view
@Sixze Is this still an issue? It's the only issue listed here holding me back on moving over to ALS-Refactored from Community.
Yes, but this issue is not critical at all and it should not prevent you from using the plugin
https://user-images.githubusercontent.com/20263103/207076722-5fb97b8c-e030-4c59-9022-f1d62e71e466.mp4 (simulated proxy on the left and right, autonomous proxy on the middle)
Looks like I've found the difference between autonomous proxy and simulated proxy: At a given montage time(eg, 0.74s👆), the mesh location on simulated proxy is 10-30cm lower than autonomous proxy.
Any hint to find what changes the mesh location? I'm assuming the CMC or the animation blueprint. (Tip: uncheck the "use less CPU when in background" in editor preference to have consistent delta time between clients)
BTW, the root motion source of mantling on simulated proxy seems have no effect at all, I tried just return on simulated proxy in AlsRootMotionSource_Mantling::PrepareRootMotion
, and the visual look the same, and this issue persists.
Also, by looking at the actor location on showdebug info, mantle is actually synced.
// Code for display mesh location `ACharacter::DisplayDebug`
DisplayDebugManager.DrawString(FString::Printf(TEXT("MeshLocation: %s MeshRotation: %s"),
*Mesh->GetComponentLocation().ToCompactString(), *Mesh->GetComponentRotation().ToCompactString()));
I suspect this issue is that animation montage and root motion source are not synchronized with each other. They play independently, there is no guarantee that they will start at the same time on clients, and the character movement component can adjust the time of root motion sources so that it is synchronized on all clients, while regular animation montages do not have such a mechanism, so their playback time may not match.
The Gameplay Ability System has a built-in mechanism for synchronizing the playback of animation montages between clients, so it's possible that this problem will go away on its own after replacing locomotion actions with abilities, but I'm not 100% sure.
https://github.com/Sixze/ALS-Refactored/blob/8dac4bed72f8db1a2ebf495f1167056cc7eeab94/Source/ALS/Private/AlsCharacter_Actions.cpp#L485
Agreed, after adding break point to this line, we can see the MontageStartTime
and play rate
are same across clients and server. So the "issue" may relate to the CMC side?
Currently, the "custom dynamic root-motion solution" in ALS is pretty hard to use(recently I tried to add a new "Climbing Up" mantling setting, the mesh and actor location never synced🥲)
The reason might be it requires the animation "position" and the actor position to be perfectly synced with each other, the way it syncs in "offline state" at runtime.
Will it better to let animation dynamically adjust itself to fit the runtime motion? like what IK does. (I am wondering whether motion wrapping would do some help with it)
GAS only sync the Position
or SectionIdToPlay
when first playing the montage, so it should not solve the issue.(FGameplayAbilityRepAnimMontage::NetSerialize
)
I also interested in how you would like to integrate GAS into ALS. The problem is every project may already have their own GAS setup (derived class of ASC and GA), so it maybe not suitable to have ALS version of those classes. Or maybe put those locomotion action abilities into ALSExmaple? To serve as a reference
I didn't get too deep into the details of how animation montage synchronization works in GAS, but it looks like the server is updating and replicating RepAnimMontageInfo
to other clients every frame, not just once per animation start.
I will isolate the GAS related stuff into a separate module so that the ALS
and ALSCamera
modules will not know anything about the abilities and will be able to work on their own. Instead, ALS
and ALSCamera
will provide an API that GAS will use to control the character.
Essentially, GAS will not be enforced, and if you don't need it, you can simply ignore it, or even cut it out of the plugin. You will lose locomotion actions, but the rest of the plugin will still work fine.
Also, as a fallback plan, there is Motion Warping that can be used instead of root motion sources, but I'm not sure if it will work in multiplayer or in situations like mantling onto a moving platform.
Currently, the "custom dynamic root-motion solution" in ALS is pretty hard to use(recently I tried to add a new "Climbing Up" mantling setting, the mesh and actor location never synced🥲)
Just found an idea to simplify it
just an idea not up to this yet.. still replicating my climbing system but wouldn't we use get server world time to syncronize it to local game time here in AlsCharacter_Actions.cpp. Just asking if you tried that yet?
if (ALS_ENSURE(IsValid(MantlingSettings->Montage))) { // TODO Magic. I can't explain why, but this code fixes animation and root motion source desynchronization.
const auto MontageStartTime{
Parameters.MantlingType == EAlsMantlingType::InAir && IsLocallyControlled()
? StartTime - FMath::GetMappedRangeValueClamped(
FVector2f{MantlingSettings->ReferenceHeight}, {GetWorld()->GetDeltaSeconds(), 0.0f}, Parameters.MantlingHeight)
: StartTime
};
if (GetMesh()->GetAnimInstance()->Montage_Play(MantlingSettings->Montage, PlayRate,
EMontagePlayReturnType::MontageLength,
MontageStartTime, false))
{
SetLocomotionAction(AlsLocomotionActionTags::Mantling);
}
}
OnMantlingStarted(Parameters);
}
Just found an idea to simplify it
I implemented this algorithm, but left it optional because while it produces an accurate start time, it does not produce the best looking result. Perhaps I missed something while implementing it, idk.
Fixed in 7a17cc0113790d27aa96bfce9bd77215555b6e99. It turns out that simply changing the animation montage time from the root motion source and disabling network smoothing is enough to solve this issue.
Also, as a fallback plan, there is Motion Warping that can be used instead of root motion sources, but I'm not sure if it will work in multiplayer or in situations like mantling onto a moving platform.
I am looking for a way to implement other type of movement. Motion Warping seems a simply and good way instead of calculate by my self. I have not been dive into it. But is there any problem when use it in network? And maybe mantle could implement by this way?