Search Unity

Animancer - Less Animator Controller, More Animator Control

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

  1. luuuuyang

    luuuuyang

    Joined:
    Aug 30, 2022
    Posts:
    5
    Hi!
    Is there a way to create a Mixer for PlayableAssetTransition?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you make a Playable Asset Transition Asset, you can assign it as an animation in a Mixer Transition.

    Or if you make the mixer in code, you can add a PlayableAssetState like any other state.

    I have no idea how well Timeline would handle being used like that though.
     
  3. luuuuyang

    luuuuyang

    Joined:
    Aug 30, 2022
    Posts:
    5
    Thanks for replying! I will try it!
    I want to explain why I asked this question, because I think Timeline Track is more intuitive and easy to use than Animancer Event
    I don't know if I'm right, if I'm wrong, please forgive my bluntness, if I'm right, is that a useful suggestion to improve Animancer Event
     
  4. SoulDesign

    SoulDesign

    Joined:
    Jul 27, 2018
    Posts:
    8
    Really good Assets!
    and your long time tech support

    i got a waring
    Possible Bug Detected: The AnimancerEvent.Sequence being modified should not be modified because it was created by a Transition.

    i have a unit that can cast skill that is based on a animtion
    i use a list of transition to store animation like this
    Code (CSharp):
    1. List<ClipTransition> clips
    the skill will add some event on these clip at born time
    and at this point the unit dont play animtion so i cant use normaly play way to get state like this
    Code (CSharp):
    1.  
    2. AnimancerState state = animancer.Play(transition);
    so i get the transition and add event like this at born time
    Code (CSharp):
    1. ani_state = clips[index];
    2. ani_state.Events.Add(0.2f, SkFrameAct);
    so when unit is death
    i clear the ani_state events because i want free all the ref
    Code (CSharp):
    1. ani_state?.Events.Clear();
    and then i got that should not be modified warn
    how can fix these promblem
    thanks a lot
     
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The warning explains how you can prevent it for one state or disable the whole warning globally. There's no harm in doing that if you are correctly managing your events, that's why it's a "Possible Bug Detected".
     
    SoulDesign likes this.
  6. br0br0br0

    br0br0br0

    Joined:
    Feb 26, 2014
    Posts:
    10
    Hello, is there a way to use the Event Names Attribute with transistion assets?

    I've my own class that has a ITransitionWithEvents that I plug transition assets into. I'm trying to use Event Names on the events within those assets.
     
  7. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you make your own transition class you can give it an [EventNames] attribute:
    Code (CSharp):
    1. [EventNames("A", "B")]
    2. [Serializable]
    3. public class MyClipTransition : ClipTransition { }
    Then if you select that as the transition type in your Transition Asset, its events will show the dropdown for those names.
     
    br0br0br0 likes this.
  8. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Hi. I'm trying to make animation like this.

    play 180 turn animation while walking and running.
    which will be good solution for this in animance document?
    what function do i need for this?
     
    Last edited: Dec 5, 2022
  9. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The 3D Game Kit example includes quick turns like that.
     
  10. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Thank you. i checked it.

    And is there a way to play stopwalk animation via locomotioMixer?
    my locomotion mixer's animations are
    Idle 0
    WalkStart 0.25
    Walk 0.5
    RunStart 0.75
    Run 1

    and i passed velocity to
    _LocomotionMixer.State.Parameter.
    so when my character is running, and if i don't input, _LocomotionMixer.State.Parameter is go back from 1 to 0.
    how can i play stopwalking animation?
    i refered 3d game kit example,, but i couldn't find solution,,
     
  11. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I don't think mixers are the right tool for that.

    They're good for blending at an arbitrary point between animations. For example, if you have Walk 0.5 and Run 1, then setting the parameter to 0.75 then you'd get an animation halfway between Walk and Run. Or with the parameter at 0.8 you'd get slightly more Run.

    But you don't want movement at an arbitrary speed, you want it to play Walk then if you start running play RunStart then Run. I'd probably do that by just having a regular ClipTransition for each of them and keeping track of which one you're currently in to determine how to play the next one. Something like this:

    Code (CSharp):
    1. [SerializeField] private AnimancerComponent _Animancer;
    2. [SerializeField] private ClipTransition _Idle;
    3. [SerializeField] private ClipTransition _IdleToWalk;
    4. [SerializeField] private ClipTransition _Walk;
    5. [SerializeField] private ClipTransition _WalkToRun;
    6. [SerializeField] private ClipTransition _Run;
    7.  
    8. private LocomotionState _LocomotionState;
    9.  
    10. public enum LocomotionState
    11. {
    12.     Idle,
    13.     Walk,
    14.     Run,
    15. }
    16.  
    17. protected virtual void Awake()
    18. {
    19.     _IdleToWalk.Events.OnEnd += () => _Animancer.Play(_Walk);
    20.     _WalkToRun.Events.OnEnd += () => _Animancer.Play(_Run);
    21. }
    22.  
    23. public void Play(LocomotionState state)
    24. {
    25.     switch (_LocomotionState)
    26.     {
    27.         case LocomotionState.Idle:
    28.             switch (state)
    29.             {
    30.                 case LocomotionState.Walk:
    31.                     _Animancer.Play(_IdleToWalk);
    32.                     break;
    33.                 case LocomotionState.Run:
    34.                     _Animancer.Play(_WalkToRun);
    35.                     break;
    36.             }
    37.             break;
    38.  
    39.         case LocomotionState.Walk:
    40.             switch (state)
    41.             {
    42.                 case LocomotionState.Idle:
    43.                     _Animancer.Play(_Idle);
    44.                     break;
    45.                 case LocomotionState.Run:
    46.                     _Animancer.Play(_WalkToRun);
    47.                     break;
    48.             }
    49.             break;
    50.  
    51.         case LocomotionState.Run:
    52.             switch (state)
    53.             {
    54.                 case LocomotionState.Idle:
    55.                     _Animancer.Play(_Idle);
    56.                     break;
    57.                 case LocomotionState.Walk:
    58.                     _Animancer.Play(_Walk);
    59.                     break;
    60.             }
    61.             break;
    62.     }
    63.  
    64.     _LocomotionState = state;
    65. }
     
  12. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Aha, okay. i'll try this.
    Thank you for the quick replies!!!
     
  13. YTGameDevDave

    YTGameDevDave

    Joined:
    Jan 3, 2015
    Posts:
    13
    Kybernetik likes this.
  14. SoulDesign

    SoulDesign

    Joined:
    Jul 27, 2018
    Posts:
    8
    add some event use event.Add like this
    Code (CSharp):
    1.        
    2. public ClipTransition ani_state;
    3. public AnimancerComponent animacer;
    4. private void InitEvent()
    5. {
    6.       ani_state.Events.Add(0.5f, TestDebug);
    7. }
    8.  
    9. public void TestDebug()
    10. {
    11.       Debug.Log("fire");
    12.       EditorApplication.isPaused = true;
    13. }
    14.  
    15. public void TestAnim()
    16. {
    17.     animacer.Play(ani_state);
    18. }
    19.  
    but when i play anim use TestAnim() the editor is paused at 0.52f normalize time
    that is not time what i want
    upload_2022-11-24_18-59-48.png

    and so the other game logic event dont match anim

    how shoud i make that rigth
    tanks a lot
     
  15. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Events are triggered on the frame when the state passes the event time so if the previous frame was before 0.5 then it will trigger the event on this frame. I'm pretty sure Unity's inbuilt Animation Events work the same way.

    The Event Utilities example has a section about pausing the state exactly on an event time if that helps.
     
    SoulDesign likes this.
  16. Danon5

    Danon5

    Joined:
    Apr 12, 2019
    Posts:
    6
    I don't understand why the Animator component has to stay enabled? Animator has a manual .Update method for finer control. The animator still fully functions while its disabled. You can use .Play, .CrossFade, etc, and it will work as long as you call animator.Update(deltaTime). Why is it that doing this still results in Animancer not working?
     
  17. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    What is the best way to do a sequence of animations. For example, let's say I have a sequence of 3 animations. I want to play anim1, then when it ends play anim2, then on end play anim3. Finally when anim3 ends exit out of the state. Thanks
     
  18. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    Hey @Kybernetik , is it possible to make integration or more detailed sample scenes with Easy Character Movement 2? (https://assetstore.unity.com/packages/tools/physics/easy-character-movement-2-193614). ECM2 has modular & robust system for those who can code, and some examples & templates are also provided for those who can't code (which really helpful for newbie like me). Animancer examples & explanation you've provided are extremely useful (thanks a bunch!), but for newbie in coding, to create more complex situation is a real headache :confused:. It'll be extremely helpful if you can help on this :)

    I guess you can re-use animation from Unity's 3D gamekit, no? As I saw other asset is also using & including these animations as examples in their package.e.g. Emerald AI 3.0
     
  19. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @Danon5 Animancer doesn't ever check if the Animator is enabled and intentionally stop working, that's just how Unity's Playables API works.

    @brokenspiralstudios A ClipTransitionSequence will handle the sequence, then you can give it an End Event to do something else.

    @Minzie The 3D Game Kit example uses Unity's inbuilt CharacterController and likely wouldn't be too hard to modify to use any 3rd party character controller system. I'd like to create a better complex character system, but that's not a remotely simple task and it's just one idea among many things I'd like to work on and if I do it would likely be well beyond the scope of a simple example so I'd likely be selling it as a separate asset.
     
    Minzie likes this.
  20. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    I used the ClipTransitionSequence as you suggested but instead of playing the full array of 3 animations, it just plays the first animation in the array and then calls OnEnd

    Code (CSharp):
    1.  
    2. public override void Enter() {
    3.             _state = animancer.Play(Activate);
    4.             _state.Events.OnEnd += OnAnimationEnd;
    5. }
     
  21. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    A ClipTransitionSequence is played as individual regular states, using each of their end events to play the next one. So your += will make the first state play the second one and also call OnAnimationEnd.

    You need to set up the end event on the last transition instead:
    Code (CSharp):
    1. private void Awake()
    2. {
    3.     Activate.LastTransition.Events.OnEnd += OnAnimationEnd;
    4. }
    5.  
    6. public override void Enter()
    7. {
    8.     animancer.Play(Activate);
    9. }
     
  22. Kazeon

    Kazeon

    Joined:
    May 22, 2017
    Posts:
    41
    Hi. I'm having a weird issue where Animancer fails to play any animation if I change the Animator's update mode to "Animate Physics". I tried to do the same thing in the example scenes and it works just fine. Why won't it work in my own scene?

    EDIT:

    Btw, will you consider opening a discord channel for support? I think it will be more convenient.
     
  23. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Changing the update mode at runtime won't work. Unfortunately, the Playables API doesn't support that.

    But if you have it in Animate Physics mode from the start, it should work as intended. I'm not currently aware of any issues with it. And there definitely shouldn't be any arbitrary differences between the examples and your scenes, so my first guess would be that there's likely something wrong with your scripts.

    I've tried using Skype for support in the past, but it always ends up with people abusing it to ask about questions without even reading the documentation or trying to find a solution on their own, or asking questions entirely unrelated to my plugins. My preferred platform is Github Issues since they make it really easy to keep track of unanswered questions, active bugs, things that have been fixed since the last release, etc. and there's no expectation of live chat so people don't just come straight to me with all their problems.
     
  24. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    hmm yes this makes sense. Reading your docs I know you indicate to setup the OnEnd in Awake but I could never figure out how to do this in a FSM. Exit() and OnAnimationEnd() debugs don't fire

    Code (CSharp):
    1.  
    2. public class NPCActivateState : NPCState {
    3.        
    4.         private bool _stateComplete;
    5.        
    6.         public NPCActivateState(NPCSM sm) : base(sm) {
    7.             build.Activate.LastTransition.Events.OnEnd += OnAnimationEnd;
    8.         }
    9.  
    10.         public override void Enter() {
    11.             animancer.Play(build.Activate);
    12.         }          
    13.  
    14.         public override void Exit() {
    15.            Debug.Log("Exit");
    16.             _stateComplete = false;
    17.         }
    18.  
    19.         private void OnAnimationEnd() {
    20.             Debug.Log("OnAnimationEnd");
    21.             build.Activate.LastTransition.Events.OnEnd -= OnAnimationEnd;
    22.             _stateComplete = true;
    23.         }
    24.  
    25.         public override bool CanExitState() => _stateComplete;
    26. }
     
    Last edited: Nov 27, 2022
  25. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    I edited the above code
     
  26. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You're only adding the event in the constructor so removing it in OnAnimationEnd means it will never fire again, but from what I can see there it looks like it should work the first time.

    If you can make a minimal reproduction project and send it to animancer@kybernetik.com.au I'll be happy to take a look at it.
     
  27. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    This ended up working but is it looking clean?
    Code (CSharp):
    1.  
    2. public class NPCActivateState : NPCState {
    3.        
    4.         private bool _stateComplete;
    5.        
    6.         public NPCActivateState(NPCSM sm) : base(sm) {
    7.         }
    8.  
    9.         public override void Enter() {
    10.             animancer.Play(build.Activate);
    11.             build.Activate.LastTransition.Events.OnEnd += OnAnimationEnd;
    12.         }
    13.  
    14.         public override void Exit() {
    15.             _stateComplete = false;
    16.         }
    17.  
    18.         private void OnAnimationEnd() {
    19.             _stateComplete = true;
    20.         }
    21.  
    22.         public override bool CanExitState() => _stateComplete;
    23. }
    24.  
     
  28. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That will add a copy of the event every time you enter the state. Just adding it in the constructor and not removing it should do what you want.
     
  29. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    hmm when I add it to the constructor, then _stateComplete never triggers

    Code (CSharp):
    1. public class NPCActivateState : NPCState {
    2.        
    3.         private bool _stateComplete;
    4.        
    5.         public NPCActivateState(NPCSM sm) : base(sm) {
    6.             build.Activate.LastTransition.Events.OnEnd += OnAnimationEnd;
    7.         }
    8.  
    9.         public override void Enter() {
    10.             animancer.Play(build.Activate);
    11.         }
    12.  
    13.         public override void Exit() {
    14.             _stateComplete = false;
    15.         }
    16.  
    17.         private void OnAnimationEnd() {
    18.             _stateComplete = true;
    19.         }
    20.  
    21.         public override bool CanExitState() => _stateComplete;
     
  30. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Where is it getting the reference to "build"? Are you sure it's actually available in the constructor?
     
  31. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Hi. i'm currently move my project from mecanim to animancer.
    and i have some questions.

    what is correspondent field of mecanim's
    Cycle Offset (at the state inspector)
    Transition Duration (s) (at the Transition inspector)
    Transition Offset (at the Transition inspector)

    and there is a jittering when transit to mixer.
    turnLeft.Events.OnEnd = Animancer.play(mixer);
    when the turnLeft animation is finished, it does not blended smoothly.
    i adjust fade duration filed at the mixer, but there are many animations to transfit to mixer. so
    the fade duration have to be changed everytime.
    Is it good to change Mixer's Fade duration in runtime?
    does the fade duration affects only at the entrance of the mixer?
    or advice for this?

    And how can i assign default state to State Machine's Default State field?
    does it assigned the top component automatically to default state?
    (How .WithDefault works?)

    Thanks
     
    Last edited: Nov 28, 2022
  32. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Cycle Offset can be set in the AnimationClip's import settings and the other two can be set in Transitions (Fade Duration and Start Time).

    The most common reason for jittering in Mixers is if you don't apply any smoothing to your parameter changes, but that's the same behaviour you'd see with an Animator Controller. Try watching the AnimancerComponent in the Inspector during the transition to see if you can determine what is actually jittering.

    Changing the Fade Duration is fine, all it does is determine how long the fade takes when you call Play.

    The Default States section explains how to use StateMachine.WithDefault. The order of components in the Inspector isn't used for anything.
     
  33. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Ah, okay.

    Do i have to check ClipState or ClipState Weight everytime before i call animacer.play?
    because If i don't, i found the clipstates are generated when i adjust its field in inspector.

    (with this wanring msg : Possible Bug Detected: AnimancerLayer.GetOrCreateWeightlessState has created 5 states for a single clip. This is most likely a result of repeated calls on consecutive frames. This can be avoided by using a different FadeMode, having the Start Time toggle disabled on a Transition, or by calling AnimancerLayer.SetMaxStateDepth to increase the threshold for this warning.)

    Code (CSharp):
    1.  if (curClipTransition.State == null || curClipTransition.State.Weight == 0)
    2.                     {
    3.                         Animancer.Play(runTurnLeft);
    4.                     }
     
    Last edited: Nov 28, 2022
  34. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The Fade Modes page explains what's happening there and the warning lists 3 different ways you can avoid it.
     
  35. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    by doing Animancer Events in Hybrid style will that avoid problems with animation interruptions? In AttackState, say I have a glow that turns on at 0.5f seconds into the sword swing animation, then the player gets hit and sends them into DamagedState. Will the glow still remain on because the GlowOff() wasn't triggered at 0.8f seconds into the animation? If so, how do I prevent this? Thanks again
     
  36. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I'd handle that in my logical state machine rather than the animations. If you're using Animancer's FSM, you could just give the AttackState an OnExitState method which calls GlowOff. Any other state machine system should have something similar.
     
  37. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    yes that's what I was thinking but interestingly enough, when I put ResetGlow() in the OnExitState method it doesn't get called if the AttackState is interrupted by an "Any" State

    Code (CSharp):
    1. public AttackState(PlayerSM sm) : base(sm) {}
    2.  
    3.         public override void Enter() {
    4.             _weapon = inventory.WeaponInHand;
    5.         }
    6.  
    7.         public override void Exit() {
    8.             _weapon.ResetGlow();
    9.         }
     
  38. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If Exit isn't getting called then there's a pretty significant bug in your state machine system.
     
  39. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    oops my fault! The OnExit() was working, it was the code on the other end that was off. Thanks again for the help!
     
  40. liheming

    liheming

    Joined:
    Jun 28, 2018
    Posts:
    3
    How to remove a State from a Layer
     
  41. liheming

    liheming

    Joined:
    Jun 28, 2018
    Posts:
    3
    Layer will reference all the played states, so i cannot release the AnimationClip. How to solve this problem
     
  42. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    There are a few options, but
    animancer.States.Destroy(clip);
    is likely what you want.
     
  43. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    How can i transit animation immediately?
    animation is played after the former animation finished.
    to be more specific, it only transit to next animation early in the former animation.
     
    Last edited: Dec 4, 2022
  44. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I'm not really sure what you're asking.

    The regular animancer.Play(clip) method will play the clip immediately. Or if you're playing a transition, you can set its Fade Duration to 0.

    If you want to wait until an animation is finished, you can use an End Event.
     
  45. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    1.
    uhh,, does the Mixer disabled when animancer play other clipTransition?
    it solved when i add this code

    Code (CSharp):
    1.  if (_LocomotionMixer.State.IsActive == false)
    2.                 animancer.Play(_LocomotionMixer);
    2.
    and how can i implement "Interruption Source : Next State" in animator controller settings field?

    thanks!
     
  46. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Animancer doesn't place any limits on which animations can transition into each other, but the Interruptions example demonstrates how you can implement such rules if you're using Animancer's Finite State Machine.
     
  47. heartshapedbox

    heartshapedbox

    Joined:
    May 27, 2018
    Posts:
    31
    Ahh, get it..

    can you explain how can i prevent this warning?
    "Possible Bug Detected: AnimancerLayer.GetOrCreateWeightlessState has created 5 states for a single clip."
    you have replied with the link of Fademode,, but i can't understand.
    i use every fademode as a parameter for Play method.. but it still happend.
    i just call animancer.Play(ClipTransition) every frame.
     
  48. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That error shouldn't be possible with any FadeMode other than FromStart. With a transition, that means you need to untick its Start Time because that causes it to use FromStart when enabled.
     
  49. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  50. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,433
    What's the best way to recover at the end of a simple animancer.Play() with root motion? No mixers, no layers, just one call to play an animation and know when it's done.

    The AnimancerState I get back continues to say IsPlaying even when the animation clip runs out. If I do an End Event, and just say .IsPlaying=false, the last frame's root motion becomes the character's velocity and it floats off into the sky. If I do nothing, the End Event gets called repeatedly. If I say .Stop(), the character goes through the floor to the fetal position.