Search Unity

Custom playable graph with 'Animate Physics' turned on

Discussion in 'Animation' started by CptKen, Aug 7, 2019.

  1. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Hi,

    I'm having trouble getting my custom animation system working properly with 'Animate Physics' turned on in the Animator Component.

    I use a completely custom playable graph which requires switching clip playables in and out constantly to achieve 'Motion Matching'. It works fine in other modes but in 'AnimatePhysics' the animation flickers continuously and the motion is all screwed up. The flicker seems to occur only when I disconnect a playable or connect a new one (which can happen very often in motion matching).

    My understanding is that 'Animate Physics' causes the animation to be processed in step with the physics update (FixedUpdate). With that in mind I've tried the following things but none have worked:

    • Updating my animation system in FixedUpdate instead of Update when AnimatePhysics is on
    • Setting the playable graph update mode to 'DirectorUpdateMode.Manual' and manually evaluating the graph in the fixed update.

    I'd really appreciate it if anyone has any insight.
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    506
    Take a look at the way they set up the graph in the Simple Animation system. Basically, they use a PlayableBehaviour class as the root of the graph with the MixerPlayable connected to it and they do all graph modifications in its PrepareFrame method which gets called as part of the graph update at whatever rate you're using.

    That's how I set it up in Animancer and I haven't had any issues like what you're describing.
     
    CptKen likes this.
  3. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Thanks. That sounds promising.
     
  4. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Ok so I modified my system to go through a custom playable behaviour. All the logic for the graph is being modified in the PrepareFrame callback and I'm using the deltaTime from the FrameData argument for all that logic.

    It's a little less jittery than before but my problem still persists for the most part with Animate Physics. Here is a video showing what I mean. The first part shows it behaving normally, the second half is when I turned on Animate Physics. It's reverting to the bind pose for a frame every time the playable graph structure is modified.



    I'm ultra stumped... I must be missing something somewhere. If anyone has any insight it would be greatly appreciated. Do I need to change the DirectorUpdateMode for the playable graph maybe?
     
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    506
    That's really odd, but I can think of a few things to try:
    • Make sure it happens when you start in Animate Physics mode too. There are some bugs with changing modes mid game in earlier Unity versions and I don't know if 2018.4 fixed them.
    • Make sure you have the DirectorUpdateMode set to GameTime when you create the graph. For some reason the default is DSPClock which has something to do with audio.
    • Maybe try adding an extra clip to the mixer at super low weight (but not 0). Alternate between disconnecting and reconnecting it repeatedly to see if it causes constant flickering. If it does then this is definitely a Unity bug.
    • Try a different Unity version. I've described the issues I'm aware of with various versions here.
     
    CptKen likes this.
  6. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Thanks.

    I've gone and done all of those things.
    • I have tested it numerous times starting in either mode without switching at run-time.
    • DirectorUpdateMode is set to GameTime
    • I created a test project to try isolate this issue. Turns out its easy to repo, see below
    • Tried 2018.4, 2019.1, 2019.2 all have the exact same issue.
    So here is my little test project I threw together. I tried to make it as simple as possible to isolate the problem. Basically, the animation starts with one clip in a mixer and then adds an additional clip every 1 second, blending them equally. Couldn't think of a more simple test.

    Turns out that with 'AnimatePhysics on,' simply creating and adding a clip playable to a mixer causes the character to go into bind pose for a single frame. This occurs whether the new clip has a weight of 0 or not and only with 'Animate Physics'. See the video below.



    At this point I'm thinking this is a bug in Unity. However, if anyone would be willing to look at the test package and see if there is something blatantly obvious that I'm doing wrong to cause this problem, I'd really appreciate that. Here's a link to the test package: https://drive.google.com/open?id=1VYuVPhHpPTnYfEwqsD-QhRieXjQ7hozb
     
  7. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    506
    I just tried it in 2018.1 and didn't see any issue.

    But m_mixer.DisconnectInput(i); doesn't exist in this version so I had to replace it with m_testAnimationComponent.Graph.Disconnect(m_mixer, i);.

    So it's possible a new bug was added after 2018.1, but I'm thinking the new mixer.DisconnectInput method has a bug even though it sounds like it should do the exact same thing.

    See if that helps, but either way you should probably report a bug.
     
    CptKen likes this.
  8. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Thanks I've reported the bug but I'm super keen for a workaround. I'll try some other alternative functions and see if I can get it to work.
     
  9. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    I swapped all the connect / disconnect functions to the old versions but I still get the same issue. They really must have introduced it in 2018.3.

    I'll just have to wait for a bug fix I guess.Thanks for your help btw. At least It's not as much a mystery anymore.
     
  10. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    506
    Turns out I was wrong, it doesn't work in 2018.1. The prefab was broken so I had to drag in a new copy of the model and copy over the component but evidently forgot to set it to animate physics mode.

    But I found a solution: replace your playable output with AnimationPlayableUtilities.Play(m_testAnimationComponent.GetComponent<Animator>(), m_target, m_testAnimationComponent.Graph);

    Taking a look at that method in IL Spy, it creates a playable output like you are, but it also calls graph.SyncUpdateAndTimeMode(animator); which is an internal method that calls into C++ so I have no idea what it actually does, but it sounds like exactly the sort of thing that could cause this issue.

    So this behaviour may actually be reasonable when whatever that method does isn't done and the bug could simply be the fact that it's internal.

    Actually, that might also solve the issue I was having in Animancer where changing the update mode after startup had no effect. It might just need me to use reflection to call that method when the mode changes.
     
    CptKen likes this.
  11. CptKen

    CptKen

    Joined:
    May 30, 2017
    Posts:
    121
    Great find. Thanks! It works for me :)