Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Simulation order and OnAnimatorMove
#1
Hi all!

First off, I want to say that ObiCloth is an amazing and very affordable product that is far superior to Unity's built-in cloth system. Kudos to the team for providing such a performant and well-documented/programmed system.

First off, I've noticed that there are pretty obvious differences in simulation quality between FixedUpdate and LateUpdate, which is to be expected, especially when the FPS is low. For instance, it seems much more likely that the cloth will clip through colliders with LateUpdate and, in general, it seems to 'crumple' more. Ideally, we'd like for the cloth's simulation order to be FixedUpdate. 

Our character movement is driven by root motion, which is applied to the character during its OnAnimatorMove function--IE, we translate the character directly from within this function. This allows us to have incredibly smooth/accurate motion and, to my knowledge, is commonly done in many video games. Our character does not use physics and only has a rigidbody (set to kinematic) because Obi requires one. All movement is driven by transform.Translate and not velocity or AddForce updates. Furthermore, our Animator update mode is set to Normal and not AnimatePhysics since we are not using physics. I should also add that our camera tracks the main character from within LateUpdate (and not Update or FixedUpdate, nor will it ever--aka, changing the update mode of the camera is not an acceptable solution for us.) Perhaps you see where I'm going with this...

The problem, then, is that, for whatever reason, setting the Simulation order to "FixedUpdate" changes the delta times received by the OnAnimatorMove function. It seems to, instead of using a DT that represents the current framerate (say, 0.016 at 60 FPS), we receive a DT of 0.02, which is the default (and ours) Unity fixed time step. I have no idea how the Obi controller code is able to 'hijack' this, but nevertheless, this introduces a problem for us where there is obvious and noticeable stutter--this is because the character movement is slightly 'off' from where the camera expects it to be if it were driven by the correct deltaTime. 

Hopefully this problem makes sense, and I'm wondering if there is a way to have cloth that still works with FixedUpdate, without that simulation order altering our update rate, or if there is some code change we can make that can enable this behavior. To recap, our game does not use physics at all and nothing happens in FixedUpdate, nor do we want it to. The only thing that we 'need' it for would be the cloth, unless there's some way to achieve a more accurate/stable simulation in LateUpdate.
Reply
#2
Sorry to bump this thread, but can anyone give me a nudge in the right direction? Thanks!
Reply
#3
(02-01-2019, 03:58 PM)MTG_Derek Wrote: Sorry to bump this thread, but can anyone give me a nudge in the right direction? Thanks!

All right--again, not trying to be rude, but it's disheartening to see other questions being answered in the forums while this one is being glossed over. Is there something I can do to illustrate the issue more or perhaps, get some sort of clarification on the problem I'm experiencing or if it should even be behaving like this at all? Surely I'm not the only person that has encountered this--I know that Obi Cloth is a complicated beast, but it'd be great to get some sort of response from the asset creator, even if it's a "I have no idea what you're talking about", so I can at least open up other routes of investigation.
Reply
#4
(16-01-2019, 06:32 PM)MTG_Derek Wrote: All right--again, not trying to be rude, but it's disheartening to see other questions being answered in the forums while this one is being glossed over. Is there something I can do to illustrate the issue more or perhaps, get some sort of clarification on the problem I'm experiencing or if it should even be behaving like this at all? Surely I'm not the only person that has encountered this--I know that Obi Cloth is a complicated beast, but it'd be great to get some sort of response from the asset creator, even if it's a "I have no idea what you're talking about", so I can at least open up other routes of investigation.

Hi there!

Sorry for taking so long to answer your question. As you've correctly guessed, Obi hijacks the update cycle of the Animator, by manually calling its Update() method (this is very easily doable using Unity's API, nothing out of the ordinary in here: https://docs.unity3d.com/ScriptReference...pdate.html). We are passing it the delta time, to keep it in sync with the physics simulation. The time passed to it depends on which update mode you select. When using UpdatePhysics, Time.fixedDeltaTime is used.

Generally you want characters to update their animation in sync with cloth physics:

- first update animation
- then update the physics
- repeat.

Code:
to recap, our game does not use physics at all and nothing happens in FixedUpdate, nor do we want it to

Well now it does, since cloth physics are physics, and animation needs to happen in sync with it. This is what setting the Animator to UpdatePhysics ensures. Using LateUpdate mode for the physics solver is not physically correct (as the delta time passed is not a fixed value, but a filtered out version of the delta time between frames), and should only be used in emergency cases.

FixedUpdate() can be called many times per frame, or none at all, depending on your fixed timestep and how much time has passed since the last frame. This is again, standard Unity behavior (or rather, standard game engine physics behavior) and nothing can be done to prevent it. So if you directly use the character position to drive the camera every frame, the cam will stutter together with the physics.

There's many possible fixes to this. The quickest, dirtiest one is to use some sort of low pass filter / damped spring on your camera, to give it some slack. Something like this will filter out any jittering in the character movement before applying it to the camera:
Code:
cam.position = Vector3.Lerp(cam.position, character.position, 0.1f);

Same for orientations, but using quaternion slerp instead of vector lerp.

An alternative would be interpolating the physics state of your character, which is the recommended solution as stated in the Unity docs, and the common solution to this issue in most games: https://docs.unity3d.com/ScriptReference...ation.html

This would interpolate the character position using the previous physics step position, its current one, and the amount of unsimulated physics time left in the current frame, ensuring buttery smooth movement.
Reply
#5
(17-01-2019, 08:07 AM)josemendez Wrote: Hi there!

Sorry for taking so long to answer your question. As you've correctly guessed, Obi hijacks the update cycle of the Animator, by manually calling its Update() method (this is very easily doable using Unity's API, nothing out of the ordinary in here: https://docs.unity3d.com/ScriptReference...pdate.html). We are passing it the delta time, to keep it in sync with the physics simulation. The time passed to it depends on which update mode you select. When using UpdatePhysics, Time.fixedDeltaTime is used.

Generally you want characters to update their animation in sync with cloth physics:

- first update animation
- then update the physics
- repeat.

Code:
to recap, our game does not use physics at all and nothing happens in FixedUpdate, nor do we want it to

Well now it does, since cloth physics are physics, and animation needs to happen in sync with it. This is what setting the Animator to UpdatePhysics ensures. Using LateUpdate mode for the physics solver is not physically correct (as the delta time passed is not a fixed value, but a filtered out version of the delta time between frames), and should only be used in emergency cases.

FixedUpdate() can be called many times per frame, or none at all, depending on your fixed timestep and how much time has passed since the last frame. This is again, standard Unity behavior (or rather, standard game engine physics behavior) and nothing can be done to prevent it. So if you directly use the character position to drive the camera every frame, the cam will stutter together with the physics.

There's many possible fixes to this. The quickest, dirtiest one is to use some sort of low pass filter / damped spring on your camera, to give it some slack. Something like this will filter out any jittering in the character movement before applying it to the camera:
Code:
cam.position = Vector3.Lerp(cam.position, character.position, 0.1f);

Same for orientations, but using quaternion slerp instead of vector lerp.

An alternative would be interpolating the physics state of your character, which is the recommended solution as stated in the Unity docs, and the common solution to this issue in most games: https://docs.unity3d.com/ScriptReference...ation.html

This would interpolate the character position using the previous physics step position, its current one, and the amount of unsimulated physics time left in the current frame, ensuring buttery smooth movement.

Hi, Jose, thanks for the response!

It's rather unfortunate that we would need to convert all of our code to use a physics-based movement 'scheme' simply to use cloth--this is not at all possible for us at this stage of our project, although admittedly, we have used physics before but ran into a lot of problems, and were never able to properly get Rigidbody interpolation working with our camera--IE, there was always jitter somewhere in the pipeline. I know it gets thrown around as something of a 'silver bullet', but in our experience (and we aren't alone), it's never provided any sort of 'cure' for camera-induced jitter (and trust me, we've tried every combination of you can imagine and possibly some you can't Lengua), nor did introducing camera smoothing via lerps/slerps. 

Furthermore, the inclusion of a Late Update mode is something of a trap as it implied to us that we could use ObiCloth with our current setup. Is there actually a legitimate use-case for having that mode if it is that noticeably inaccurate compared to the FixedUpdate version? And I realize that cloth simulation is a physics-based process, but I mistakenly assumed that your implementation would take care of it under the hood, or that there would be some kind of 'minor' trade-off. Again, more our fault than anything for not thinking through it. While I appreciate the suggestions, it still requires us to move back to an entirely physics-based movement scheme, or at least, requires us to move characters with cloth differently than non-cloth characters, which is still 'messy.' In theory, the workarounds sounds great--in practice, they require a ton of work. 

I wonder if there is some way to 'fake' constant delta times while still feeding ObiCloth the late update DTs--something of an extrapolation mode, I suppose. Or can we update the cloth via a Coroutine running at a rate equivalent to our physics tick (obviously, this would still suffer from some inaccuracy)? Phrased differently, can you think of anything that we can do to preserve LateUpdate as our cloth method--I would even be open to trying crazier stuff like using two different animators, one to drive motion and one to drive physics, but I have no idea whether that's viable, let alone possible.

Once again, thanks for the lengthy response!
Reply