Animation with root motion synchronization in multiplayer

Short version: How can be animations with root motion synchronized in multiplayer (or networking in general) so the animations are fluent and synchronized as much as possible?

Long version: Movement of characters in my project is controlled by root motion of animation, so my code calculate speed and angular speed from user input: user clicks on scene, NavMeshAgent calculates path and result is used to navigate the character. Each player has it’s own character and I want to synchronize their movement using networking.

  • It’s not authoritative server networking: each client is responsible for moving their character.
  • When a character receives new destination from user, first few corners from the path are sent to other players - when first destination is reached, next corner is sent, so all players keeps track of character’s path.
  • Each client calculates movement of the character from the path and animate it accordingly.
  • When the character is too long away from expected position (expected = on it’s “home” client), it’s moved there and rotated accordingly.

But this is not working well:

  • According question 589291 animations are calculated in Update() and not FixedUpdate() (and then interpolated) which causes following:
  • When fps on clients is different, character makes different stepd and turnd on corners which makes animation different and their movement too. It’s all out of sync.
  • In other words, unlike physics, animation movement (root motion) is apparently not predictable.

So my question is: is there a way to prevent this, or root motion is unusable for multiplayer (making it singleplayer-only feature)?

Notes:

  • From my description it should be clear I use movement prediction. Reason is simple: when I “just” synchronized animation and position, it was everything but fluent, especially in corners where speed and angular speed is changed in much bigger rate then 15 updates per seconds which is default update rate for networking. Of course I could change the rate, but I need to think about bad quality connection (which is not my whim, but I cannot write more).
  • Everything is tested on single PC so the problem is not from bad connection.
  • For now I’m using animation and models from Stealth project. This is for testing only, of course.

Did you get any insight on this? I am facing a similar problem.

2 Answers

2

@AxelMGarcia I was “just” learning Unity that time, so I let it go after some time and never had to solve this in my job later. However I have two ways I would go if I would need to solve this problem again in future. One solution is to just give up, move the objects in fixed update and then animate according the movement, i.e. give up animation-controlled movement. This is the safe way. The another is to set “Update Mode” to “Animate Physics” in Animator component - this ‘solution’ needs investigation whether it actually works or not. According execution order ( Unity - Manual: Order of execution for event functions ) it should NOT work. Animator component documentation does not specify this (in fact, it’s apparently outdated), however script documentation ( Unity - Scripting API: AnimatorUpdateMode ) says that it actually DOES update during fixed update instead of standard way. Please, let me know if you try it.

Nearly a decade later, I stumble upon this thread.

Man! I feel like I found an ancient relic lol. So, I was just studying Unity’s new NetCode for GameObjects (it didn’t exist when this thread began), and yup the very exact same issue!

My player was being moved by the RootMotion of its animation, and the synchronization was soooo messed up, even on local host and client setup. After days of scouring the internet, looking up the docs. and StackOverflow (none of which helped), I stumbled upon this.

@Aithoneku , I’m glad to inform you (after 9 years), that setting the “Update Mode” of the animation to “Animate Physics”, does indeed work like a charm!

Thank you!

Yeah, it feels ancient, but at the same time, these (almost) 10 years flew incredibly quickly. Anyway, glad to be useful. We switched to Unreal, so I wouldn't be much help hew today. But I definitely suggest you should test that under VERY bad networking conditions (there should be some simulation options if I remember correctly), like huge lag & huge packet loss. Things like that can turn out to be fragile, so make sure you're not building on shaky foundations.

Personally, after a bit of experience, I wouldn't depend on animation-controlled movement in networked environment any more; it can bite you a lot. Networking is very tricky and it's IMHO best to have as much control in your own logic as possible and Unity black-boxes can be unreliable in weird conditions... (But of course, this also depends on what kind of game/app you're making.)