Hello,
I need the opinion of people who know how UCharacter and UCharacterMovement replication works.
In my game, I need a character to be attached with a relative position of 0 to a component of another replicated actor. The component deliberately uses a different relative position between the client and the server.
The problem is that the replication of the character forces it to move and ignores the relative position of its parent. [See image 1]
I would like to force the replication of the character to be based on its relative position when attached or when I define it (With a bool or something) as it does by default when it is on a platform. [See image 2]
For the moment the best way I have found is to force the location I want in an override of UCharacterMovementComponent::OnMovementUpdated
. I’m not sure it a good method.
Thanks!
Hello!
I was able to fix the issue using based movement and a custom movement mode.
You should know that both the server and the client use the relative transform of BasedMovement.MovementBase
for character replication. If MovementBase
is NULL
, the absolute transform is used instead.
MovementBase
is set automatically by movement modes like the walking mode when the character lands on the ground, or cleared (set to NULL
) when the character is falling.
So I created a new custom movement mode to set the base component when the player is attached, using an override of UTagCharacterMovementComponent::PhysCustom
:
void UTagCharacterMovementComponent::PhysCustom(float deltaTime, int32 Iterations)
{
if (CustomMovementMode == CUSTOM_MOVEMENT_MODE_STUCKTOZONE)
{
PhysStuckToZone(deltaTime, Iterations);
}
Super::PhysCustom(deltaTime, Iterations);
}
void UTagCharacterMovementComponent::PhysStuckToZone(float deltaTime, int32 Iterations)
{
// Code with SetBase()
}
Now, the client will replicate the character’s position based on the attached component instead of the world transform. The tricky part is that based movement is generally used without attachment.
-
Without attachment: if my base component moves 50, the character also moves 50 cm.
-
With attachment: if the base moves 50 cm, the character moves 50 cm from the attachment plus another 50 cm from the movement base logic so it moves 100 cm in total.
But thanks it possible to simply cancel based movement updates during this mode by overriding UTagCharacterMovementComponent::UpdateBasedMovement
:
void UTagCharacterMovementComponent::UpdateBasedMovement(float DeltaSeconds)
{
if (MovementMode == MOVE_Custom && CustomMovementMode == CUSTOM_MOVEMENT_MODE_STUCKTOZONE)
{
// Disable base movement update when using the stuck zone
return;
}
Super::UpdateBasedMovement(DeltaSeconds);
}
I’m not sure if it’s the best solution, but it’s definitely much cleaner than recalculate and forcing the client’s position in UCharacterMovementComponent::OnMovementUpdated
.
Hope this helps someone else!