Search Unity

Animancer - Less Animator Controller, More Animator Control

Discussion in 'Assets and Asset Store' started by Kybernetik, Oct 8, 2018.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Ahh damn! Oh well. It is a little strange as it only happens on the first play of an animation clip.

    Hey I found a solution to the issue where Animancer component wasn't updating. It seems that if I have more than 8 components on an object, it wont update the Animancer Component continuously.
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  3. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    I'm on 2020.3.16f1. It was a bit strange, didn't seem to matter what components I got rid of as long as there were 8 or less in the end. I shuffled things around a little though and it's working great now.
     
  4. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    I'm using the latest version and following the Restart Current State example, which uses state.Events.OnEnd to call a method that resets the state.Time to zero.

    But it's giving me the warning
    Possible Bug Detected: An End Event did not actually end the animation
     
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    LukeDawn likes this.
  6. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    Installed the fix. Thanks for that :beer:
     
  7. ge01f

    ge01f

    Joined:
    Nov 28, 2014
    Posts:
    121
    @Kybernetik Is there a way to play the animation speed based on a curve? So that it can be normal at 1.0, and then slower and faster if the curve goes to 0.5 or 2.0?

    Id like to implement variable wind up and recover times based on stats, and dont want to bake the animation frames differently, and would prefer to implement it with dynamic curves.

    Any way to do that in Pro?

    Maybe just setting speed = curve.Evaluate(...)? Would that need to happen in Update or Late Update?

    Thanks!
     
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You could do it in Update (since you want to set the speed for that frame before it advances the animation time) or you could implement IUpdatable and register it in the Pre-Update list.

    Simply setting the speed would work, but would give inconsistent results depending on the delta time for each frame unless you set the Animator to Animate Physics mode. So if you want real precision you'd need to do some more complex calculations based on the individual speed changes which would be difficult if you want to use an actual curve but should be pretty simple if you only want fixed speeds for certain parts of the animation.
     
  9. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135
    Hello there, has anyone implemented Animancer with Photon PUN2? I would like to discuss, and compare the approach I have so far to find better ways to do the state syncronization. This is what I got so far, and it's working.

    Code (CSharp):
    1.  
    2. public abstract class BaseState : Animancer.FSM.State
    3. {    
    4.         public Actor Actor { get; set; }
    5.  }
    6.  
    7. public sealed class Actor : MonoBehaviourPunCallbacks, IPunObservable
    8.     {
    9.         [Tooltip("The local player instance. Use this to know if the local player is represented in the Scene")]
    10.         public static GameObject LocalPlayerInstance;  
    11.  
    12.         [SerializeField]
    13.         private AnimancerComponent _Animancer;
    14.         public AnimancerComponent Animancer => _Animancer;
    15.    
    16.         public ClipTransition _IdleAnimation;
    17.         public ClipTransition _WalkAnimation;
    18.  
    19.         [SerializeField] private Rigidbody _Rigidbody;
    20.         public Rigidbody Rigidbody => _Rigidbody;
    21.    
    22.         public enum StateKey { Idle, Walk}
    23.         public BaseState CurrentState { get; private set; }
    24.         private NewIdleState _IdleState = new NewIdleState();
    25.         private NewWalkState _WalkState = new NewWalkState();
    26.  
    27.         private readonly StateMachine<StateKey, BaseState> FSM = new StateMachine<StateKey, BaseState>();      
    28.  
    29.         private void Awake()
    30.         {
    31.             // #Important
    32.             // used in GameManager.cs: we keep track of the localPlayer instance to prevent instanciation when levels are synchronized
    33.             if (photonView.IsMine)
    34.             {            
    35.                 LocalPlayerInstance = gameObject;
    36.                 // #Critical
    37.                 // we flag as don't destroy on load so that instance survives level synchronization, thus giving a seamless experience when levels load.
    38.                 DontDestroyOnLoad(gameObject);
    39.             }
    40.  
    41.             _IdleState.Actor = this;
    42.             _WalkState.Actor = this;
    43.             FSM.Add(StateKey.Idle, _IdleState);
    44.             FSM.Add(StateKey.Walk, _WalkState);
    45.             FSM.ForceSetState(StateKey.Idle, _IdleState);
    46.          
    47.         }
    48.  
    49.         private void Update()
    50.         {
    51.             if (photonView.IsMine)
    52.             {            
    53.                 if (Input.GetKeyDown(KeyCode.Space))
    54.                 {
    55.                     FSM.TrySetState(StateKey.Walk);
    56.                 }
    57.  
    58.                 if (Input.GetKeyDown(KeyCode.Tab))
    59.                 {
    60.                     FSM.TrySetState(StateKey.Idle);
    61.                 }
    62.             }
    63.         }
    64.  
    65.         public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    66.         {
    67.             if (stream.IsWriting)
    68.             {
    69.                 stream.SendNext((int)FSM.CurrentKey);
    70.             }
    71.             else
    72.             {
    73.                 // Network player, receive data              
    74.                 StateKey key = (StateKey)stream.ReceiveNext();
    75.                 FSM.TrySetState(key);
    76.             }
    77.         }
    78.     }
     
    Last edited: Aug 16, 2022
    hopeful likes this.
  10. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I've never used PUN and don't have much networking experience, but I have a couple of general suggestions:
    • You aren't initializing the ForceEnterIdleState delegate. If you aren't using it you should just remove it, but otherwise take a look at the new Default States system I added in Animancer v7.0.
    • You're also only setting the CurrentState property on startup but not changing it when the state changes. If you want it there for convenience, change it to
      public BaseState CurrentState => FSM.CurrentState;
      so that you don't need to set it.
    • Converting enums to and from strings is quite inefficient (and the ToString creates garbage). It's far more efficient to convert them to and from ints:
    Code (CSharp):
    1. stream.SendNext((int)FSM.CurrentKey);
    2. ...
    3. var key = (StateKey)stream.ReceiveNext();
    4. FSM.TrySetState(key);
    That would still allocate a bit of garbage since ReceiveNext returns an object and a quick look at the PUN documentation didn't show any better way to receive an int, but that's still far less than it would be allocating for each string.
     
  11. ge01f

    ge01f

    Joined:
    Nov 28, 2014
    Posts:
    121
    Thanks! I think fixed speeds at different parts of the animation would probably be the best solution then, if the curve yielding inconsistent results is a problem. That may actually work out to add some variance, I will have to try it out.
     
  12. sherzhen

    sherzhen

    Joined:
    Jun 28, 2015
    Posts:
    13
    Hey, thanks for such a useful tool! I use your asset in almost every project. In the last update, I can't figure out how to use LinearMixerTransition (like in previous versions it looked and worked a little differently). No matter how I try to create a LinearMixerTransitionAsset, I keep getting an error:
    "ArgumentOutOfRangeException: Incorrect threshold count. There are 3 states, but the specified thresholds array contains 0 elements."
    Perhaps I did not fully understand something. Thank you in advance!

    - Unity 2020.3.16f1
    - Animancer 7.1
     
  13. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Can you give me a bit more detail about what you're actually doing? I'm not getting any error from just creating a LinearMixerTransitionAsset, adding some states to it, and playing it.
     
  14. sherzhen

    sherzhen

    Joined:
    Jun 28, 2015
    Posts:
    13
    Yes, sorry, I forgot to add that to repeat this you need to either preview transition, or go to play mode and pass LinearMixerTransitionAsset as a parameter to AnimancerComponent => Play ()

     
  15. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  16. sherzhen

    sherzhen

    Joined:
    Jun 28, 2015
    Posts:
    13
  17. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135
    Thanks for the prompt reply, in the code I posted I had a few lines for previous attempts, I completely forgot I could cast the Enum to a int, like you showed me, now the code is cleaner, and better yet working with several clients ;)
     
  18. Shibli

    Shibli

    Joined:
    Feb 9, 2015
    Posts:
    6
  19. vonSchlank

    vonSchlank

    Joined:
    Jan 5, 2017
    Posts:
    37
    Hello,
    I'm not familiar with Animancer, but I need to create runtime a sequence of animation clips (variable number of clips, with adjustable properties such as Clip InTime, Duration or Speed), with variable length of interpolations/extrapolations, and sample any given second of the created sequence to pose a character.
    Something like creating a Timeline runtime, and set a character to take the pose of the resulting animation at, let's say 1.08, then set an other to 3.22, ect...
    I haven't read the docs yet, i'd like to know first: is Animancer the right tool for this job?
     
  20. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That would certainly be possible with a bit of work.

    A ClipTransitionSequence would let you set up a series of clips with end times, fade durations, and speeds which can all be freely modified at runtime.

    That's just a series of individual states linked together by End Events though so you can't simply set the time and have it apply the correct clip and fade values in the middle of the sequence. But it would be easy enough to write a function that goes through the sequence to calculate those values.
     
  21. vonSchlank

    vonSchlank

    Joined:
    Jan 5, 2017
    Posts:
    37
    Thanks for the quick reply!
    Ah, ok, so i can't just grab a resulting PlayableGraph and Evaluate it on a certain time, if i understand correctly, but i can get a certain individual state (the 3rd clip, for example) and Evaluate it on, let's say, 1.05 of it's own time, right?
     
  22. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Accounting for the fading between animations would be a bit more complex, but yeah that's essentially it.
     
  23. vonSchlank

    vonSchlank

    Joined:
    Jan 5, 2017
    Posts:
    37
    OK, thank you, i'll consider my options and we'll see...
     
  24. Censureret

    Censureret

    Joined:
    Jan 3, 2017
    Posts:
    363
    Hello i am looking to buy the pro version of this asset but i am concerend that it may not work with Photon or multiplayer can anyone clear this up? :) Thank you in advance
     
  25. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  26. MyOwnGames

    MyOwnGames

    Joined:
    Jul 21, 2014
    Posts:
    25
    Hello!
    I didn't find how to mirror animations with Animancer.
    Is it possible to do it? Or do I need to duplicate each animation to use the normal AND mirrored animations (eg if the character can wield its weapon in any hand)?

    edit : I saw in this thread that it still wasn't possible to do it last year, but that it might be possible since v5.0, any update?

    Thank you!
     
    Last edited: Sep 13, 2021
  27. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Yeah, unfortunately the Playables API doesn't have the ability to mirror at runtime so you need to duplicate the animation and mirror the copy in its import settings.
     
  28. MyOwnGames

    MyOwnGames

    Joined:
    Jul 21, 2014
    Posts:
    25
    Ok, thank you for your extra fast answer. Have a nice week!
     
  29. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135
    Take a look at my post above, perhaps it might help a little
    Animancer - Less Animator Controller, More Animator Control
     
  30. DaphidtheAphid

    DaphidtheAphid

    Joined:
    Aug 3, 2017
    Posts:
    2
    Hi @Kybernetik! Thanks so much for making this library! It really makes managing animations easier and more powerful! I just have a weird question regarding Unity 2021.2.0b12. (I know it's really far into "beta" territory but I want to try and play around with the new Chromebook building capabilities). Sadly, I can't even seem to get the example scenes from Animancer to run without this error popping up:
    MissingMethodException: Method not found: UnityEngine.Animations.AnimationLayerMixerPlayable (screenshot with log attached).

    My gut reaction is that this is probably just an issue from the instability of a super beta-ish Unity build and that there's not much we can do about this. But I thought I would post a question here in the off chance that there's something easy/obvious that I'm missing! Thanks so much for your time and consideration and thanks again for making such a useful tool!
     

    Attached Files:

  31. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That does seem like the sort of issue that's likely to be fixed once that version comes out of Beta. There's probably nothing we can do about it, but it might be worth reporting as a Unity bug to make sure they know about it.
     
  32. DaphidtheAphid

    DaphidtheAphid

    Joined:
    Aug 3, 2017
    Posts:
    2
    Thanks for your prompt reply! I had a feeling it would be something like that heh. I'll see if I can bug unity about it! Thank you again!
     
  33. NeedsLoomis

    NeedsLoomis

    Joined:
    Mar 22, 2017
    Posts:
    57
    Heyo! Sorry for being a bit noobish, but I can't for the life of me figure out how to stop an animation without resetting everything to its starting position (using Stop) or perma-locking every value to its most recent position (using isPlaying = false). Doing the latter, then straight up disabling the animancer component is how Im currently dealing with it.

    Basically I want to play a clip and don't know how to return control to the rest of the Unity. Thanks in advance!
     
    Last edited: Sep 19, 2021
  34. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you want Animancer to stop controlling anything, animancerComponent.Playable.PauseGraph() should be what you're looking for.

    You can also achieve the same thing by setting the Disable Action to Pause so you can disable the AnimancerComponent to have it call that method.
     
  35. ace7171363

    ace7171363

    Joined:
    Sep 19, 2021
    Posts:
    3
    I am new to Animacer and programming in general i am following your 2D directional character controller example for my practice game it works good but i want the animation to transition like in the Game bastion that is when i go from N/up to E/right it should look like it is turning N>NE>E while in your example it switches instantly N>E.
     
  36. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Using Vector3.RotateTowards to gradually move your facing vector towards the direction the player wants to go would likely achieve the effect you want.

    I would also recommend Directional Animation Sets for that rather than Mixers since they would be easier to set up and more efficient.
     
    ace7171363 likes this.
  37. ace7171363

    ace7171363

    Joined:
    Sep 19, 2021
    Posts:
    3
    Thanks for the response
    so i tried to modify directional character controller a little bit to give my animations turn affect
    Code (CSharp):
    1.  void inputmanager()
    2.     {
    3.         Vector3 currentpos = transform.position;
    4.          Movement = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    5.        
    6.         Vector3  inputVector = Vector3.MoveTowards(currentpos, Movement+currentpos, transitionspeed);
    7.         if(inputVector!=Vector3.zero)
    8.         {
    9.             _Facing = inputVector;
    10.             updateMovemetSet();
    11.             _CurrentAnimationSet.Snap(inputVector);
    12.         }
    13.         else
    14.         {
    15.             play(_Idle);
    16.         }
    17.     }
    it does have a turning affect but is not smooth at all what am i doing wrong
     
  38. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Try something more like this:
    Code (CSharp):
    1. private Vector2 _Movement;
    2.  
    3. private void UpdateModement()
    4. {
    5.     var input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    6.     if (input != Vector2.zero)
    7.     {
    8.         _Facing = input;
    9.         _Movement = Vector2.MoveTowards(_Movement, input, transitionspeed * Time.deltaTime);
    10.        updateMovemetSet();
    11.        _CurrentAnimationSet.Snap(_Movement);
    12.     }
    13.     else ...
    14. }
     
    ace7171363 likes this.
  39. ColtonRamos

    ColtonRamos

    Joined:
    Nov 4, 2015
    Posts:
    15
    Hey! I'm very interested in using Animancer because in Mecanim, animations on different layers or different clips in blend trees will all fire their events on top of each other, resulting in e.g. footstep noises playing multiple times even if only one walking animation is playing.

    Is there a way I can use the AnimancerEvents to get around this issue? I can't seem to get my events on my MixerTransition2D to fire at all. upload_2021-9-21_22-31-16.png
     
  40. ColtonRamos

    ColtonRamos

    Joined:
    Nov 4, 2015
    Posts:
    15
    Ok, weird, I got this to work. I didn't do anything but delete and re-add the exact same events to get it working. Weird.
     
  41. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Yeah, that should work fine. I can't think of any reason why it wouldn't.

    Also, you should untick the Sync toggle for the idle animation. You want the movement animations synchronized so their foot movements line up, but that isn't relevant to an idle animation and you don't want the idle to affect the speed of the others.
     
  42. helloroy

    helloroy

    Joined:
    Jun 23, 2016
    Posts:
    42
    Hello, I making a fighting game and want to play punch animation any time, when I fire the animation too frequently, the error occurred below:

    ArgumentOutOfRangeException: AnimancerLayer.GetOrCreateWeightlessState has created 5 states for a single clip. This is most likely a result of calling the method repeatedly on consecutive frames. This can be avoided by using a different FadeMode or calling AnimancerLayer.SetMaxStateDepth to increase the threshold for this warning.
    Parameter name: depth
    This issue will be occurred in example 01 -> 02 "Good CrossFade from Start then Idle" button too.

    Any idea to avoid this?

    Thanks
     
  43. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The Playing and Fading example explains why it happens and as the error says, you can use AnimancerLayer.SetMaxStateDepth to increase the warning limit as high as you want.
     
  44. helloroy

    helloroy

    Joined:
    Jun 23, 2016
    Posts:
    42
    Thanks Kybernetik, any other idea to avoid the error without SetMaxStateDepth? is there any method to check is fading completed?
    And when I use animator with trigger, it will not case any problem.
    I know that animancer is different with unity animator, but it's a bit confuse to animancer beginner.
     
  45. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    animancerComponent.States gives you various methods for accessing states and you can check their Weight to determine if fading is complete (it will be 1 after fading in).

    Using a trigger in an Animator Controller will give completely different behaviour because they can't create new states at runtime so it's not possible for a state to fade into itself.

    If you can explain the exact behaviour you want (or post a video of an Animator Controller showing it) then I can tell you how to get the same effect in Animancer.
     
  46. helloroy

    helloroy

    Joined:
    Jun 23, 2016
    Posts:
    42
    Thanks Kybernetik, as your suggest, I using AnimancerComponent.States.Current.Weight < 1 to check and seems working fine.
     
  47. wb_nizar

    wb_nizar

    Joined:
    Jan 7, 2020
    Posts:
    3
    This is going to sound like a dumb question, but is there a way to create a list of Unshared assets of multiple types? For instance, I have ClipTransitionAsset.Unshared and PlayableAssetTransitionAsset.Unshared objects that I want to put in one list. I can do so with ITransitionWithEvents, but I want to be able to pull those Unshared objects out and access their methods without having to identify the type and casting them as that type of Unshared object. I thought the parent object could be something like
    AnimancerTransitionAsset.UnShared<AnimancerTransitionAsset<AnimancerTransition<AnimancerState>>,
    AnimancerTransition<AnimancerState>,
    AnimancerState>>
    but it also returns an error. I might be missing something obvious here, but any help would be greatly appreciated!
     
    Last edited: Sep 25, 2021
  48. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The first generic argument in UnShared is
    TAsset : AnimancerTransitionAsset<TTransition>
    which clip and playable asset can't share so it would need to be done using an interface.

    Which methods are you wanting to call?
     
  49. wb_nizar

    wb_nizar

    Joined:
    Jan 7, 2020
    Posts:
    3
    Bummer-- I wanted to organize all my animancer transition assets in one list so I could use one enum type for all the animations. I know I could do this if I just use the assets and use AnimancerTransitionAsset as the base, but I also wanted to leverage the UnShared functionality.

    Edit: Nevermind, I guess you can't do that with the non-UnShared assets
     
  50. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I had a quick go at making a non-generic UnShared type but it looks like it would need a whole bunch of ugly casting to work properly with the current class hierarchy. It should be possible to do with some refactoring so I'll take another look at it in more detail for the next version, but it might need to wait for the next major version if it requires any significant changes.