Search Unity

Animancer - Less Animator Controller, More Animator Control

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

  1. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    upload_2024-1-24_17-30-26.png

    upload_2024-1-24_17-30-56.png

    upload_2024-1-24_17-31-14.png

    I normally try not to be condescending, but come on man. You can literally just do
    var percentage = state.NormalizedTime % 1;
    .
     
  2. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    Hello,

    I was wondering if it is possible to emulate a nested blend tree in Animancer using Mixers. I am converting another project over to use Animancer and the mecanim animation controller contains such trees. I've successfully used Controller Transitions for this, but I would prefer to have an Animancer-only solution by using Mixers.
     
  3. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  4. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    Awesome, thank you! I've basically been doing all my learning from the examples so I didn't think to read, you know, the *actual* user manual lol.
     
  5. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,443
    Today I was interested in your SoloAnimation class, to help pose a bunch of shop mannequins in the editor.

    I found that a tiny change would let me preview the entire animation clip in the editor instead of just the first frame. You had already done all the work, it just took exposing the time parameter.

    Code (CSharp):
    1.  
    2. [Range(0f, 1f)]
    3. public float sampleTime = 0f;
    4.  
    5. protected virtual void OnValidate()
    6. {
    7.     if (IsInitialized)
    8.     {
    9.         Speed = Speed;
    10.         FootIK = FootIK;
    11.     }
    12.     else if (_ApplyInEditMode && enabled)
    13.     {
    14.         _Clip.EditModeSampleAnimation(_Animator, sampleTime * _Clip.length);
    15.     }
    16. }
     
  6. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That's a neat idea. The Inspector controls already let you scrub the time in Play Mode, so I'll see if I can just expose that in Edit Mode as well. The only difference would be that your field remembers its value through domain reloads.
     
  7. Clef1345

    Clef1345

    Joined:
    Jul 9, 2019
    Posts:
    1
    Is it possible to add MixerState<float> to a list or array?
    im trying to do something similar in Transition Nesting part of Mixer Creation from user manual, except instead of two MixerState<Vector2> i have one List<MixerState<float>> (float because child mixers are linear, not directional), and instead of assigning each MixerState<float> one-by-one i just used for loop to add each one to list, compiler dont mind that, but when i try play mode it gives error with " InvalidCastException: Specified cast is not valid. " when code trying to add MixerState<float> to a list
     
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The exception says it's a problem with the cast, not with adding the result of the cast to the list. Try logging the mixer.GetType() before the cast to confirm the type of each object. One or more of them must not be a linear mixer.
     
    Clef1345 likes this.
  9. daenius

    daenius

    Joined:
    Sep 7, 2021
    Posts:
    11
    Silly question, is `ControllerState.ParameterID` your equivalent of PropertyName but made specifically to deal with parameters from an `AnimatorControllerPlayable` that doesn't discard the name string at run time? This humble simple `struct` feels like a surprising game changer so far.

    I started experimenting with the various parametrized `ControllerTransition`s for some of the more complex nested blend trees from other assets for easier direct Inspector setup. Here are some significant differences I've noticed so far:

    • Switching to AnimatorControllers CAN actually blend themselves instead of awkwardly warping your animated object
    • Avoids the insufferable Mecanim workflow of making you basically declare same logical parameter twice in completely disjointed places (once in editor and one more in code in giant static C# class of `Animator.StringToHash` if you can't spell like me but want to reference them in code)
    • Supports using multiple AnimatorControllers on the same object at the same time with `AnimancerLayer`s with each of them actually working CORRECTLY for closed source exclusive features like run time mirroring

    All this seems to make AnimatorControllers feel far more usable and intuitive than before because it does have a decent UI for setting up nested blends with previewing in the editor so for me most of its problems came from how confusing and brittle it felt in code. I haven't observed any problems going from playing AnimationClip or ClipTransition to AnimatorControllerTransition and back yet. Feels almost too good to be true, is there any downside to doing this or would you still recommend sticking with the various `MixerTransition` or `MixerTransitionAsset`s?

    On a side note, upon examining the `PlayableGraph` I'm guessing the reason why Animator awkwardly warps your GameObject when switching `RuntimeAnimatorController` is due to the Animator component being directly wired to the `AnimatorControllerPlayable` instead of having a master `AnimationMixerBehaviour` like Animancer that handles blending from one `Playable` to the next. Is this the correct explanation?

    EDIT: instead of*
     
  10. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I don't remember ever coming across PropertyName before.
    • As you've noted the main difference in functionality seems to be that they don't give easy access to the string and discard it entirely at runtime.
    • Decompiling their ToString method shows that they're doing something to detect conflicts so if there's a hash conflict they can list out all the source strings which would be nice.
    • Constructing new PropertyNames seems to be about 4-5 times slower than my PropertyID in the Unity Editor (presumably due to that conflict detection stuff), but the runtime performance seems to be the same so it shouldn't be an issue.
    • The only thing I'm actually using the strings for is displaying them in the Inspector so I'm pretty tempted to just swap to their system for the conflict detection even if it makes my Inspector a bit slower due to needing to parse the text of their ToString output.
    You might be interested in my Weaver plugin which can procedurally generate that C# class for you. It's included in Weaver Lite for free.
    The main downsides I can think of with Animator Controllers are the fact that Animancer Events trigger based on the time of the current state without knowing about what that state actually is or when it changes and their annoying tendency to ignore you if you call Play multiple times in the same frame, but if all you have in the controller is a single Blend Tree then neither of those should matter. Otherwise, the main functional differences should be the way they each handle synchronization.
    I have no idea. AnimatorControllerPlayables create other child playables for their layers and states in a structure somewhat similar to how I do it in Animancer (though they use some internal features which we don't have access to) so in theory both systems should give the same outcome, but there are a bunch of weird unexplainable behaviours like this which don't line up for no apparent reason.
     
    daenius likes this.
  11. daenius

    daenius

    Joined:
    Sep 7, 2021
    Posts:
    11
    Appreciate the detailed analysis of what PropertyName does under the hood! VFXGraph basically takes the same approach you did with ParameterID (but with a class instead of struct) https://docs.unity3d.com/Packages/c...tility.ExposedProperty.html?q=ExposedProperty

    I have been using PropertyName in Scene-level singletons that need to handle look-up and lazy loading for spawned objects. They are serializable so I've been abusing that to replicate how you made `ControllerTransition` show whether the property is properly resolved in the inspector with warning colors and stuff.

    In `PlayableGraph` terms it almost feels like a Scene-level `IExposedPropertyTable` kind of, as ultimately with any generic behaviour tree it's useful to have a hierarchical blackboard as the complexity goes up. Btw I saw your rant about Timeline property binding, you might get a kick out of this open source asset (it's on UPM too) Basically this guy figured out how that stuff is serialized so now you can actually feed the correct bindings into Timeline to dynamically play Timelines without having to include the concrete bindings in the Timeline prefab. In the case of `PlayableAssetTransition` I found that I don't need to do a `mancer.Playable.Graph.SetResolver(director)` and simply let the Timeline take care of itself. Not the biggest fan of how he implemented the editor workflow but it's free open source asset so I'm sure you could come up with a much better take on that.

    Thanks! This is going to be all kinds of useful especially these days Unity is infatuated with feeding magic string queries into everything from VFX graph to shaders to UIToolkit and essentially turning C# into JS. The InputSystem generates something like this but nothing else does for whatever reason.

    Luckily I have everything setup to exactly never call Play more than once per frame on any object and I use small separate `PlayableGraph`s to evaluate other things so I ended up just using TimeNotificationBehaviour instead so I'm actually not aware of that edge case with `AnimancerEvent`. It is technically part of the Timeline API but it works for anything you throw at it. You can make it use itself or any other Playable as a time source and it'll automatically track its own time and looping behaviour to sync with the time source.

    Good call on the synchronization! I tried it just now and I think it potentially also depends on the exact animation assets themselves when it comes to how the final output looks? From your comparison it seems Unity tries to go the extra mile of calculating foot phase and probably other stuff while your mixer is more about faithfully showing the blended output like an actual 3D animation program. I think in BlendTree terms yours is more like "here's a DIRECT BlendTree with weight parameter calculation presets that will apply different weighting math". I can see very valid use cases for both approaches tbh and luckily Animancer is flexible at letting pick and choose for the situation. I might actually argue that Unity's approach opaquely makes assumptions about what you want whereas you have us pick what we want though, but I guess frustration with Mecanim behaviour opacity is why we all here xD
     
  12. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    daenius and saskenergy like this.
  13. yupengfei

    yupengfei

    Joined:
    Nov 10, 2017
    Posts:
    21
    The animation seems to produce displacements that the physics engine is unaware of. I wrote a piece of code to apply reaction, and while the idle animation is playing, the physics engine seems to still handle the raycast with a standing posture. As a result, when clicking on a blank space, Raycast determines that it is a hit, but when clicking on the thighs and calves, there is no hit. I encountered the same bug when dealing with sword slashing enemies.
    I'm writing my first game using animancer, so I don't know if it's an animancer problem or a unity problem, and how should I fix it?
    Below is my code, and the Attachment is screen recording. Thank you.
    Code (CSharp):
    1.  
    2. var p = Mouse.current.position.ReadValue();
    3. Ray ray = Camera.main.ScreenPointToRay(p);
    4.  
    5. // Raycast to find a ragdoll collider
    6. RaycastHit hit = new RaycastHit();
    7. if (Physics.Raycast(ray, out hit, 100f))
    8. {
    9.     Character.hitReaction.Hit(hit.collider, ray.direction * Character.hitForce, hit.point);
    10. }
    11.  
     

    Attached Files:

  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Do you have Kinematic Rigidbodies on the collider objects? That may help.

    Otherwise, there likely isn't anything Animancer can do to help because the underlying animation system is all Unity internal stuff so Animancer doesn't know anything about what you're actually animating. You would likely get the same result when playing the animation through an Animator Controller.

    Also, you don't need to declare a new RaycastHit, you can just do
    out var hit
    in the Raycast call.
     
  15. yupengfei

    yupengfei

    Joined:
    Nov 10, 2017
    Posts:
    21
    I tried both Kinematic and no Kinematic Rigidbodies, but they both do not work. I'm sure others have encountered the same problem, but I don’t know how to solve it, and I haven’t found a solution.
     

    Attached Files:

  16. yupengfei

    yupengfei

    Joined:
    Nov 10, 2017
    Posts:
    21
    I think it it caused by animator update mode, when set to normal, it works, and when set to fixed, it is buggy.
     
  17. yupengfei

    yupengfei

    Joined:
    Nov 10, 2017
    Posts:
    21
    I noticed that the collider has a little displacement when kinematic rigidbody is unchecked, can you tell me why?
     
  18. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If it's not Kinematic, then the physics engine is controlling it with velocity/collisions/etc. so you're likely seeing it after those things have moved it a bit before the animation gets re-applied again next frame.

    Another thing you could try would be calling Physics.SyncTransforms in LateUpdate to ensure the physics engine sees anything the animation has moved.
     
  19. yupengfei

    yupengfei

    Joined:
    Nov 10, 2017
    Posts:
    21
    OK, thank you
     
  20. ArIaNFury008

    ArIaNFury008

    Joined:
    Dec 22, 2019
    Posts:
    20
    Hey, I need some tips if you could help me. Thanks for the great Product!

    because I had a problem with Runtime AvatarMasking in Animator Controller I switched to Animancer Pro and I spent the whole week reading documentation.

    but something I can't understand and I think it's not optimized is using a lot of checking which is needed when using Animacer. it was easy and efficient in Unity Animator.

    for example now in my code, I have to check a lot of "if statements" like this which wasn't like before:

    Code (CSharp):
    1. if (move.magnitude != 0 && !_character.IsCrouched() && _character.IsGrounded() && !_IdleToCrouchAnimationEnd)
    2. {
    3.     _Animancer.Play(_Walk);
    4. }
    maybe it works well for now but what when there are many other Animations? any little changes to the game make bugs to old written Code which wasn't a cast when I was using Animator, You set the Parameter and let Animator do the Job.

    I was so hyped for Animancer but every day my mind changes a little bit and Prefer the Animator Controller more. (I LOVE Animacer don't get me wrong!)

    It would be much better if there was a complex behavior with many animations and layers to see how we should set up.

    About Documentation:
    it's really good thanks for the effort, but after reading the whole document also I think I read every subject more than twice it still does not give me an idea of how I can implement it in my situations, every time I make a change then something goes wrong and I start to read AGAIN :D

    Any tips would help. Thanks, Appreciate! (Think about game like The forest or sons of the forest in my situation)

    About State Machine:
    I highly disagree with using a strict state machine for more complex character controllers or character controller in general. A real production open world character controller could have things like swimming, combat, weapon in hand but not in combat, weapon in hand but climbing, fall from high ledges, out of stamina , Spell Casting ,dodge, transition state from swimming to walking , etc etc and most of these state are usually highly dependent on one other and share code. As you build out your character controller and add more features, your current grouping of states might become more ambiguous .You can see how this can get out of hand really fast . Also a game isn't just a random character on a flat ground. You have things like VFX , Sound, game Events, animations, Hit boxes, UI, IK etc that could be highly state dependent. All of this requires monobehaviours and extremely tight interstate communications.

    EDIT: I don't think there is going to be a way, In big Projects that have many Animations, State machine is not useful for most cases, and writing spaghetti code is something that can't run from it. I saw many big projects like Inside, Far Lone Sails, Death Door, and The forest codes were unbelievable I was like why are you doing this way ???? :(.
     
    Last edited: Feb 26, 2024
  21. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    Quite trivial but important question. ive got an animation and when i play the same animation again it somehow wont get played. i have to stop animancer, then play the animation but that totally kills the transition and results in a hard cut. whats the best way to avoid that. here is my code:



    Code (CSharp):
    1.  public void PlayTrick(AnimationClip animationClip, float transition)
    2.     {
    3.       //  _animancer.Stop();
    4.         var trickState = _animancer.Play(animationClip, transition);
    5.         trickState.Events.OnEnd = PlayGroundAnimation;
    6.     }
     
  22. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @ArIaNFury008 Thanks for the feedback, I really appreciate discussions like this because it makes me consider the way I'm developing things and helps me understand what people are expecting out of the system.
    Your code wasn't like that before because you had set up those conditions in the Animator Controller instead. The logic has to be declared somewhere, it's just a question of where.

    Consider what the Animator Controller equivalent of that code would be. You'd have 3 parameters and then every transition into the walk state would be checking them.
    • How long would it take to set up all those parameters and transition conditions? Certainly a lot longer than writing that one line of code.
    • How do you know what the conditions for those transitions are? You need to check them all individually and make sure they don't have any differences instead of just reading one line of code which says "anything can transition to the walk animation with these conditions".
    • How do you find out what's controlling the "IsCrouched" parameter? You'd have to look through all your code for places using that string instead of just looking at the _character.IsCrouched() function.
    • How can you debug it to find out why a particular transition is or isn't occurring? You can't, you just have to observe it from the outside and try different things until something seems to work instead of being able to use breakpoints and logs to properly debug code.
    There are a lot of advantages to having all that in one line of code, but with all that said, I wouldn't write it like that anyway because there are probably too many responsibilities in one place and as you noted, it would only get more and more unwieldy as more complexity is added to the character.

    The State Machines examples, 3D Game Kit example, and Platformer Game Kit all demonstrate how you can start to approach more complex characters without having any functions looking like your one.
    It seems like you're comparing an already functional Animator Controller to code you haven't written yet, which is hardly fair.

    You can't simply set a parameter and expect an Animator Controller to work, you have to create parameters and states and transitions and configure all their conditions, and only then can you just "let the Animator do the job".

    Unsurprisingly, the same is true for Animancer or any other system, it will only work once you have set up the required logic and given it the necessary animations.

    If your code breaks whenever you make any little changes, that's very much an issue with the way you're writing your code. The only real remedy for that is experience, though it surprises me to hear the implication that Animator Controllers don't break so easily because they absolutely do.
    I'm not really sure what tips I could give because you don't seem to have a specific problem. Animancer isn't forcing or even encouraging you to write code like that, so if you can see that it's a problem then you can try approaching it in a different way. You said you've read the whole documentation more than twice, yet somehow the supposedly problematic code you posted doesn't actually resemble any of the more complex examples I mentioned above.
    I'm struggling to understand what you're trying to say here and in the rest of your post.

    I agree that using a strict state machine system is bad.

    Animator Controllers are a strict state machine system. You must set them up in the Unity Editor and can't modify them at runtime. You must define everything the character can do in a single Animator Controller. You have very limited options for controlling and getting data from the system at runtime. And so on. Everything about them is extremely strict.

    Animancer's state machine system is as open and un-strict as it could possibly be. It's entirely separate from the animation system so you don't even have to use it at all. States can be components or ScriptableObjects or regular C# classes. You can completely change the structure of anything whenever you want. The system lets you do basically anything you want. It's literally the opposite of strict.

    All those other things you mentioned like events, IK, and hit boxes can be done in Animancer just as easily. Take my Platformer Game Kit's Hit Box system for example: you can set up an attack's hit boxes alongside its damage and animation details with a nice interactive preview window. That extra stuff on top of the regular transition only took a few simple scripts to implement, so I'd love to hear how you could have achieved the same thing any easier with an Animator Controller.

    No single tool can cover every use case or appeal to every user so it's entirely possible that Animancer isn't the right tool for you, though my impression from reading your post is that the issue lies with the way you're approaching the code rather than anything Animancer is actively preventing you from achieving.
     
    ArIaNFury008 likes this.
  23. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  24. ArIaNFury008

    ArIaNFury008

    Joined:
    Dec 22, 2019
    Posts:
    20
    Thanks this helped me! finally, last night I Could convert all my Animator Controller to Animancer, and the Problem I had with AvatarMask is gone and it works very well in Animancer. now that I have written the whole Logic for my previous code I can Imagine how to add more complexity to work in various ranges. Your support and activity are amazing Thanks!

    Edit: If anyone has a problem like understanding and can't do Complexity Codes from the start, just start with basic parts and let it WORK then do Refactoring and add more Complexity which will be much understandable and better to implement.
     
    Kybernetik likes this.
  25. daenius

    daenius

    Joined:
    Sep 7, 2021
    Posts:
    11
    I have a small utility add-on for Animancer that I would like to share with the wider community. What would be the most appropriate way to do so?
     
  26. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Posting it as a Github Issue is probably the best place for it.
     
  27. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  28. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    Hi I'm playing a sequence of animations. I want to be able to trigger a callback after the final animation in the sequence has completed. This plays the entire sequence but does not trigger the callback at the end. Thoughts?


    Code (CSharp):
    1. public void PlayClipSequenceCallback(ClipTransitionSequence sequence, Action callback) {
    2.             var state = _animancer.Play(sequence);
    3.  
    4.             var lastState = _animancer.States.GetOrCreate(sequence.LastTransition);
    5.             lastState.Events.OnEnd = () => {
    6.                 callback?.Invoke();
    7.             };
    8.         }
     
  29. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You should be adding the event to the last transition rather than its state.

    Replace your ClipTransitionSequence.cs with the attached file, it has a bunch of new things including an EndEvent property on the sequence which is a shortcut for the last transition.
     

    Attached Files:

  30. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    After copying over the new version, I get a bunch of errors
     

    Attached Files:

  31. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I forgot I've changed the ICopyable interface. Just remove that interface from the top and delete the Clone and CopyFrom methods.

    Or if there are still errors after that, you could just grab the EndEvent property from the new file and since that's all you really need.
     
  32. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    got it to work with this but just curious of your thoughts for efficiency, performance, or correctness. Thanks again!
    Code (CSharp):
    1. public void PlayClipSequenceCallback(ClipTransitionSequence sequence, Action callback) {
    2.             _animancer.Play(sequence);
    3.             sequence.EndEvent = new AnimancerEvent(1, callback);
    4.         }
     
  33. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    For correctness, there's a few potential issues:
    • You should generally assign the events for a transition only once on startup rather than every time you play it. Obviously that doesn't apply if you're actually using different callbacks each time, but that'd be an unusual use case.
    • If the last transition in the sequence had any other events in it, you would be triggering OptionalWarning.LockedEvents for modifying its events after playing it.
    • Hard coding the end time to 1 isn't ideal since its a visual parameter which should be configured by artists in the Inspector. Add this property to ClipTransitionSequence and use it instead:
    Code (CSharp):
    1.         public Action OnEnd
    2.         {
    3.             get => LastTransition.Events.OnEnd;
    4.             set => LastTransition.Events.OnEnd = value;
    5.         }
    For performance, there's nothing wrong with that method itself but you might be creating a new delegate object every time you call it unless you're storing the Action yourself. That's another reason why configuring the events only once on startup is usually best, because then the transition will just keep the Action for you.
     
  34. ArIaNFury008

    ArIaNFury008

    Joined:
    Dec 22, 2019
    Posts:
    20
    Hi, OnEnd Events is running more than once should I use
    Code (CSharp):
    1. _CurrentState = _AttackLayer.CurrentState;
    2. _CurrentState.Events = null;
    Each time the events calls?

    How can I run the OnEnd only once?
     
    Last edited: Mar 15, 2024
  35. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Normally you would use the end event to play another animation, which would automatically clear the events from the previous animation.

    If you aren't doing that, then yeah you can manually clear the events or you could just use a regular event instead of the end event. The End Events page explains the differences between them.
     
    Last edited: Mar 15, 2024
    ArIaNFury008 likes this.
  36. VodaLechebna

    VodaLechebna

    Joined:
    Dec 29, 2020
    Posts:
    4
    Hello, I want to play sword attack animation on upper body and walking animation on lower body. I tried layers with Avatar Mask, but blend doesn't look right:

    Original attack animation (full body)
    2024-03-1602-58-50online-video-cutter.com-ezgif.com-video-to-gif-converter.gif

    Blend with idle animation:
    2024-03-1603-01-47online-video-cutter.com-ezgif.com-video-to-gif-converter.gif

    Avatar Mask:
    Сни23wewefwef23мок.PNG

    Interestingly, it looks the same no matter if I set layer.IsAdditive to true or false.
     
  37. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Layer masking and blending is handled internally by Unity so Animancer has no control over the result and you would see the same thing in an Animator Controller. The result you're seeing is about what I'd expect from the body being tilted differently due to the legs being in a different pose.

    You could try the experimental Weighted Mask Mixer system which gives you individual control over each bone. It's still a vary bare bones system because almost no one has given me proper feedback on how they want to use it, so if you can give me any suggestions on how you would like it to work I might finally be able to develop it into a real user-friendly feature.
     
  38. VodaLechebna

    VodaLechebna

    Joined:
    Dec 29, 2020
    Posts:
    4
  39. darkriver41

    darkriver41

    Joined:
    May 5, 2019
    Posts:
    7
    Hello, is there an example with a mix of mixers and ClipTransitions playing together ?
    I tried to do this my self but i find that the mixer animation still plays if i play another ClipTransition manually. And i get a warning in the inspector saying the total weight of all states in this layer is != 1 or something similar. I suspect this is easy to do but i didn't find how i can blend between the mixer and the solo animation or the other way around.
    Thanks
     
  40. darkriver41

    darkriver41

    Joined:
    May 5, 2019
    Posts:
    7
    I took a look at the 3D kit sample and i now understand what was my mistake, i was calling mixer.stop before playing another clip, i guess that's handled internally
     
  41. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Yeah, playing something will automatically stop the previous animation so manually stopping it would be harmless. But if you want to smoothly fade the new animation in you need to let it fade the old one out instead of stopping it immediately.
     
    darkriver41 and hopeful like this.
  42. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    Hello, I was wondering if you have suggestions for adding parameters to state changes in the FSM. I basically want to add a generic Dictionary<string, object> so I can have dynamic parameters. My only idea is I need to derive StateMachine and override all the state setting methods to add this extra argument. But they all call each other so the override would basically be copying all the logic in the methods which would be a maintenance hassle when upgrading. Maybe there's a better way to go about this that I'm not thinking of?
     
  43. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Animancer v8.0 will have a new Parameter Binding system which is somewhat similar to your dictionary idea. It's still a while off being ready for testing, but if all your states have access to the AnimancerComponent you could put your dictionary there which should make upgrading pretty straightforward. You could avoid modifying Animancer by making your own class that inherits from AnimancerComponent to put the ddictionary in.

    Alternatively, you could make a class which inherits from StateMachine and put your dictionary there. Then it can have a static property like this to access it during state changes:
    Code (CSharp):
    1. public static Dictionary<string, object> CurrentParameters
    2.     => (StateChange<YourStateType>.StateMachine as YourStateMachineType).Parameters;
     
    Last edited: Mar 27, 2024
  44. brokenspiralstudios

    brokenspiralstudios

    Joined:
    Oct 20, 2021
    Posts:
    45
    Right now I'm using a LinearMixer for Idle, Walk, Run. When the player performs a melee attack, then AbilitySystemBusy = true. This is used as a bool guard to prevent the LinearMixer from playing the locomotion animations. When the melee attack is finished, then AbilitySystemBusy = false, allowing the Locomotion animations to play again. Problem is upon return, it snaps back to the locomotion animation as opposed to a smooth transition back. Any thoughts? Thanks!
     
  45. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You're most likely not specifying the fade duration or telling it to play the mixer transition when you want it to fade back. Telling it to play the mixer state directly will instantly play the state.
     
    brokenspiralstudios likes this.
  46. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    The inheriting of the state machine is what I have now. I'm basically following your pattern from the 3D game kit example so my states implement Owned State. Thus I have access to the state machine within the state and thus the parameters. I copy over the parameters to the actual state on the OnEnterState method. This does concern me a little because every time a new state tries to execute it copies over the parameters to this intermediary. In theory the state has it's own copy and never has to access the intermediary so this should be fine but I'd prefer to pass it in the TrySetState methods to only copy it when the state is actually going to change.
     
  47. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Why are you copying parameters at all instead of just letting the states directly access the same dictionary?
    That makes no sense. OnEnterState is only called when the state is entered which is already what you want.
     
  48. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    Because after a state is entered, other states are competing to be the next state but often they have to wait until CanExitState of the current state returns true. These other states have their own set of parameters so they are essentially overwriting the shared Dictionary with their values. Thus, the current state needs to copy over the parameters to its own space to use while it is the active state. I don't just need the parameter values when a state is entered, I might need them during the Update and even for logic when the state exits.
     
  49. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Why not have the states extract the values they want into strongly typed fields then? That way you only need to do dictionary lookups and casting when entering the state and aren't creating and rearranging multiple dictionaries all the time.

    Another option might be to just have two central dictionaries; an active one which everything controls and then when entering a state you copy it into the other one for the current state to use. That at least avoids having a new dictionary for every new state.
     
  50. emcom-ai

    emcom-ai

    Joined:
    May 6, 2022
    Posts:
    6
    Yeah, this is probably the direction I'll eventually head but the system I'm building is still in the early stages so I don't necessarily have all the states I'll be using nor all the parameters they might need so I'm just stuffing them in the dictionary for now. Plus when I thought about overriding the state setting methods, it would be easier with just adding a single Dictionary argument.

    The dictionary copying isn't great but they are generally small (for now?). I basically have a planning system that queues up states to be executed and the default plan which sits in memory is executed most of the time so only references are being copied. When something different happens, I do have to create the parameters (and thus dictionary) on the fly but these events last multiple seconds so creation and GC are hopefully not too frequent.