Download

Animation works on client, not on server...

A complete stab in the dark:

Server side, animations on clients only update when they communicate with the client, which forces the pose refresh. The reason you see the little dotted lines on the animation graph (and why it’s updating during movement) is because in it’s default state it’s constantly checking the server-replicated speed property. Double-click the default node in the animation graph, and you’ll see the replicated speed property it polls each update. I’m assuming your character’s default state-machine node, on the other hand, has no such setup. Maybe just the ‘play animation’ action? So it only communicates the ‘play animation’ message upon playing - but then stops communicating. Because there’s no back and forth communication you get the initial pose change (upon play), but then the server does not refresh the pose.

A quick search in the documentation section turned this up:

https://answers.unrealengine.com/questions/25313/client-character-animations-dont-run-on-server.html

The bottom reply is probably relevant to your situation.

Odd, my searching (on the 9th) turned up nothing relevant in the answerhub so I created a bug report for it that day. I do have 2 meshes (skeletal). I’ll look further into that post and my situation. Thanks!

I tried the bottom reply first, no change in result. Turns out that having 2 skeletal meshes on the character was the culprit. I removed the skeletal mesh that was included in the First Person Template (the arm and gun model). Then I removed the node in the input Blueprint that referenced that mesh. Once I did that, the animation played on both server and client just fine!

Chambered, you have my gratitude! I knew it had to be something super simple, I just couldn’t find it…

I don’t need your gratitude but you need to get your thing straight, here I put my effort to show you that it IS about replication.
I just do this during my coffee time and capture it, feel free to ignore it. Like I “guessed” it was easily done when replication is setup.
Under same condition, first person blueprint template, listen server and client, I keep the arm mesh and migrate the Owen pawn from Animation example content.
Of course, I setup the animation and trigger and state, they don’t automagically just happen.

It was never about additional mesh/skeleton, it is “do you even understand how the engine work or not”.
Big thanks to Redditor /u/AODBAMF, he posted this very helpful thread on /r/gamedev and fantastic capturing result.

Now, with above being said. It might actually be true that the best way to get correct answer is to post a wrong answer on internet.
I can’t stand that you are satisfied with your wrong approach and will probably lead some future newbie that are clueless to assume your way is correct.
So that’s the only reason I made this video, I never really want to help you, either directly or indirectly because of your attitude.
Please stop claiming you do how many years in programming for big company and other unrelated thing, truth is you didn’t want to trace the code, you didn’t want to understand how the engine work on basic level,
you just want to plug nodes in and expect them to work like a charm. Those people you bashed are correct, and your answer to your problem is still the wrong way to do it.

A bit of an old thread, but I ran into this issue today, and Google was not helpful at all. It did point me to this thread, but there’s no actual solution here. So I’ll outline the bug/problem I’ve found that causes this and my work around.

The problem: If you have a derived character with more than one skeletal mesh, only the first (the Mesh member) will animate on the server if it’s a client. It’s related to this check in SkeletalMeshComponent::ShouldTickPose()

This is actually pretty gross. I have no idea why SkeletalMeshComponent is directly referring to a gameplay class. Bad programmer, no cookie.



// Remote Clients on the Server will always tick animations as updates from the client comes in. To use Client's delta time.
const bool bRemoteClientOnServer = CharacterOwner && (CharacterOwner->Role == ROLE_Authority) && CharacterOwner->Controller && !CharacterOwner->Controller->IsLocalController();


When the components go to tick, if this component is part of a ACharacter derived class, and it’s remotely controlled and it’s on a server, it doesn’t get the normal tick. CharacterMovementComponent has the responsibility to do it, but doesn’t. It only assumes that it has one mesh, the Mesh member, and updates that and only that.

Unfortunately the ACharacter and UCharacterMovementComponent classes are quite tightly coupled and monstrously large, so a good general solution isn’t easy.

However, I’ve fixed MY issue. There’s a couple other calls to TickPose() in UCharacterMovementComponent that aren’t addressed with this fix, so I may have to come back to this issue. I ended up having to create a custom character movement component and overriding one method.



void URobotCMC::MoveAutonomous(float ClientTimeStamp, float DeltaTime, uint8 CompressedFlags, const FVector& NewAccel)
{
	if (!HasValidData())
	{
		return;
	}

	CharacterOwner->UpdateFromCompressedFlags(CompressedFlags);
	CharacterOwner->CheckJumpInput(DeltaTime);

	Acceleration = ConstrainInputAcceleration(NewAccel);
	AnalogInputModifier = ComputeAnalogInputModifier();
	PerformMovement(DeltaTime);

	CharacterOwner->ClearJumpInput();

	// If not playing root motion, tick animations after physics. We do this here to keep events, notifies, states and transitions in sync with client updates.
	if (!CharacterOwner->bClientUpdating && !CharacterOwner->IsPlayingRootMotion() && CharacterOwner->Mesh)
	{
                // My hack, tighly coupling this component to my derived character class, sadly. I'd really like a good solution.
		ARobotCharacter *robot = Cast<ARobotCharacter>(CharacterOwner);

		if (robot != NULL)
		{
                        // Tick my other components.
			if (robot->TorsoComponent)
			{
				robot->TorsoComponent->TickPose(DeltaTime);
			}

			if (robot->HullComponent)
			{
				robot->HullComponent->TickPose(DeltaTime);
			}
		}

		CharacterOwner->Mesh->TickPose(DeltaTime);
	}
}



So DarkHalf, you were right - the issue was related to you having an unexpected number of skeletal meshes on your derived character, and having the blueprint somewhere other than the default mesh.

I hope this helps someone. I am very tempted to refactor the ACharacter and movement component to be a little less grody, but the maintenance overhead involved is scary.

Thanks very much for bringing this up Backov. This certainly isn’t a great way to do things, we are going to refactor it.

Ya, I’m not super happy with it. I’m glad I’ve brought it to your attention.

I know this will be a hell of a refactor, but what’s the chance we can get a nicely decoupled design for these 3 tightly coupled components? Perhaps a move towards a more composition based system. For instance, is it possible to break out the client side prediction to something that can be used outside of the CMC? Do all the different movement types need to be hardcoded into the giant ACharacter class, or can they be broken out into strategy classes and used when needed?

Being an UE4 newbie despite having worked with it pretty hardcore for the last couple months, I’m in a poor position to come up with a good plan for a refactor of that level, but I’d really like one. There does seem to be room for improvement there.

We have actually been talking for a while about the ‘special relationship’ that Character and CharacterMovementComponent have. Originally this started because ActorComponents did not support replication, so had to rely on the Character class for that. We have been slowly moving things from Character into the CMC, but as you point out, there is still more to do. We will keep working on it, as you point out, it’s quite a big refactor, and we don’t want to break existing projects. Another refactor we would like to do is break out the client prediction code so it can be re-used by non-Character classes.

Thanks for your feedback, you make some very good points and we take it very seriously.

I just ran into this as well.

Here is my temp solution until epic has a more full featured fix. This version has the added benefit of not needing to subclass the CMC, specifying game level components. Unfortunately there will still be issues where the CMC only accounts for Mesh in other parts of the code, but that is okay for us right now. Thanks all!

void UCharacterMovementComponent::TickCharacterPose(float DeltaTime)
{

if (GetWorld()-&gt;HasBegunPlay())
{

[INDENT] TArray<UActorComponent*> skeletalMeshComponents = CharacterOwner->GetComponentsByClass(USkeletalMeshComponent::StaticClass());

	for (auto& Component : skeletalMeshComponents)
	{

[INDENT] check(Component->IsA(USkeletalMeshComponent::StaticClass()));
USkeletalMeshComponent skelMesh = (USkeletalMeshComponent)Component;

		// skip CharacterOwner-&gt;Mesh since it is already ticked
		if ((skelMesh != CharacterOwner-&gt;Mesh) && skelMesh-&gt;IsActive() && !skelMesh-&gt;bHiddenInGame)
		{
			[INDENT]skelMesh-&gt;TickPose(DeltaTime);
		}[/INDENT]
	}[/INDENT]
}

[/INDENT]

James, was this code ever refactored? I’m on UE 4.7.3 now and I want to check if I need to remove this piece of code that we have locally.

Bumping this. Just checking if latest code has support for multiple skeletal meshes on one character