What's the Best Way to Implement Smooth/Lagless Animation Replication?

Initially I set a variable in PlayerState via an execute on server event to replicate it to all clients and have it check at the character’s anim blueprint Update Animation event to trigger the animation. With this method I found that the animation will almost always lag or trigger late at client side. Then I changed to just simply execute a multicast event to play the animation and found that it is smooth and almost no lag.

I figure the PlayerState way will use less network resource and that it will automatically handle re-animation when player disconnect and reconnected while multicast would consume more resource and I have to manually replay the animation when player reconnected.

Any suggestions?

Via Blueprint:

  1. Create a Blueprint struct to hold a montage and its relevant info (Play rate, section etc).
  2. Add this as a variable to your character that replicates via a rep notify.
  3. On the client, make sure the rep notifier for the variable plays the montage using the replicated information.
  4. On the server, ensure you fill in this replicated montage variable when you play an animation and call ForceNetUpdate.

After that, any delay in the animation playing will be caused by the latency between server & client.

This is all we have done in GB for server-to-client replication of general animations, though its a C++ version.
We include the time the animation started, so if the animation will jump forward to the appropriate time.

This is good for when an animation begins playing without network relevance.
Without this ‘catch up’, as soon as the character becomes relevant, the animation would play from start to finish, regardless of when it actually began.

Changed to your method and it’s working really well now. Thanks!
One more question though, how do you jump forward the animation? Montage play does not have a parameter to specify animation start time.

In C++, you can call “<animation instance>->Montage_SetPosition(<montage>, <new position>)” to jump to an exact position, but after checking, it doesn’t appear to be exposed to the Blueprint system.

Something to expose in a Blueprint function library and give to @Rama I guess.

Managed to expose the function in blueprint by creating a new c++ AnimInstance class. Thanks for the info again!
In case anyone interested, here’s the code

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Animation/AnimInstance.h"
#include "MyAnimInstance.generated.h"

class FIRST_API UMyAnimInstance : public UAnimInstance
	UFUNCTION(BlueprintCallable, Category = "Animation")
	void MyMontage_SetPosition(const UAnimMontage* Montage, float NewPosition);


// Fill out your copyright notice in the Description page of Project Settings.

#include "First.h"
#include "MyAnimInstance.h"

void UMyAnimInstance::MyMontage_SetPosition(const UAnimMontage* Montage, float NewPosition)
	Super::Montage_SetPosition(Montage, NewPosition);

Hey guys, sorry for classic necro practice but I thought expanding on this legendary post might benefit others as well.

Probably bringing eternal dishonor to my family with this entry level question but how does one synchronise client and server clocks?

Its not so much sychronise as in just get the difference :slight_smile:
In any case, getting the current server worl time - GameState > GetServerWorldTimeSeconds.

Might be the lack of sleep but I’m having a hard time following these instructions. Any chance I could get the blueprint version of this with pictures to follow?