Search Unity

Animancer - Less Animator Controller, More Animator Control

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

  1. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    720
    I don't see any methods by this name, either in the source code or in the documentation. I am using v7.4.2
     
  2. ununion

    ununion

    Joined:
    Dec 2, 2018
    Posts:
    275
    finally i found the solution,the problem is about CharacterController if you use root motion with that,you will get strange things happen.

    so if you want to set a position with character controller and animator,you should do like this
    Code (CSharp):
    1. var cc = o.GetComponent<CharacterController>();
    2.             cc.enabled = false;
    3.             o.transform.position = new Vector3(5, 0, 5);
    4.             cc.enabled = true;
     
  3. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  4. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    720
    Got it, thanks! That's straightforward enough.
     
  5. ununion

    ununion

    Joined:
    Dec 2, 2018
    Posts:
    275
    hi kybernetik,a question here,how can i set onEnd event in editor?
    i have figure out to set normal event in editor like this
    UnityEventTools.AddVoidPersistentListener(t.SerializedEvents.Callbacks[j], event);
    but i don't know how to set onEnd event and serialized it.
     
  6. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The End Event is the last item in that array.
     
  7. ununion

    ununion

    Joined:
    Dec 2, 2018
    Posts:
    275
    thanks,it works!
     
  8. ununion

    ununion

    Joined:
    Dec 2, 2018
    Posts:
    275
    if I want to force replay an clipTransition,is this the only way and correct to do that?
    Code (CSharp):
    1. animancerComponent.Play(attack,attack.FadeDuration,FadeMode.FromStart)
     
  9. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you set the transition's Start Time to 0 it will automatically use FadeMode.FromStart.
     
  10. hugo-purespark

    hugo-purespark

    Joined:
    Oct 29, 2022
    Posts:
    15
    Hi.

    I have the bone transform rotation in LateUpdate but the bone does not rotate. Still have the same issue. While the spheres are moving.


    void Update()
    {
    float time = Mathf.PingPong(Time.time * speed, 1);
    LeftHandSphere.position = Vector3.Lerp(LHStartPosition, LHEndPosition, time);
    LeftHandSphere.rotation = Quaternion.Lerp(LeftHandSphereRotationStart, LeftHandSphereRotationEnd, time);
    }

    IEnumerator FingerRotate()
    {
    for (s = 0; s <= 100f; s += 0.2f * Time.deltaTime)
    {

    bone.transform.Rotate(new Vector3(s, 0, 0), Space.Self);

    yield return null;
    }
    }
    void LateUpdate()
    {
    StartCoroutine(FingerRotate());
    }

    I can see in the inspector that the rotation value changes but nothing happens when in Play mode.
     
  11. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You're starting a new coroutine every LateUpdate and once each coroutine yields it will no longer be running in LateUpdate so the only bit that will take effect in LateUpdate is the first iteration which rotates it 0 degrees so you wouldn't be able to see it doing anything.

    I'm not sure what you're trying to do, but you probably need something more like this:
    Code (CSharp):
    1. private float s;
    2.  
    3. void LateUpdate()
    4. {
    5.     if (s > 100f)
    6.         return;
    7.  
    8.     s += 0.2f * Time.deltaTime;
    9.     bone.transform.Rotate(new Vector3(s, 0, 0), Space.Self);
    10. }
     
  12. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    hey, super quick question, is there a way to smooth out the parameter values?

    Code (CSharp):
    1.   public void PlayGroundAnimation(float horizontal, float vertical)
    2.     {
    3.         _mixerState.Parameter = new Vector2(horizontal, vertical);
    4.     }
    in mecanim i was able to do it this way:
    Code (CSharp):
    1.  _animators[i].SetFloat(name, value, 0.25f, Time.deltaTime);
     
  13. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    RobertOne likes this.
  14. GamePowerNetwork

    GamePowerNetwork

    Joined:
    Sep 23, 2012
    Posts:
    257
    [SOLVED]
    The solution to my problem was adding the IOwnedState interface to my states.


    Original question:
    ---------
    Hello! I'm loving the asset so far!

    I just have one question I didn't see covered in the docs. In the examples, the ActionState calls a method "GetNextState".. and from my understanding that comes from "StateExtensions".

    However I don't see a way of accessing StateExtensions or how to get the "GetNextState" method.
     
    Last edited: Apr 9, 2023
  15. Kybernetik

    Kybernetik

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

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    When I create an AnimancerState using AnimancerState.Clone(), how do I remove/destroy it when I'm finished with it?

    The cloned state appears in the inspector, but doesn't get removed from the inspector when I try to use Destroy() or DestroyPlayable() on it. Is there a better (or proper) way to destroy a cloned state?
     
  17. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I just did a quick test and the destroyed clone disappeared from the Inspector. Are you sure you're destroying the right thing?
     
    LukeDawn likes this.
  18. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    I think so
    Code (csharp):
    1.  
    2. var aState = _animancer.Play(clip, 0.2f);
    3.  
    4. ...
    5.  
    6. var newState = aState.Clone();
    7. newState.Time = 0;
    8. var currentState = _animancer.Play(newState, 0.2f);
    9.  
    10. ...
    11.  
    12. newState.Destroy();
    13.  
    Animancer Pro Version 7.4.2
     
    Last edited: Apr 10, 2023
  19. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135
    Hello @Kybernetik,
    Is there a way to create a Directional MixerTransition2D from code? I would like to assign the animation clips at runtime stored in a data asset, the data asset is a list of ClipTransitions that contains locomotion clips, strafe movement clips, the latter I will like to add at runtime depending on the data asset assigned to the equipped weapon.
     
    Last edited: Apr 10, 2023
  20. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @LukeDawn that looks basically the same as what I tried and I still can't replicate the issue you're describing. Can you send a minimal reproduction project to animancer@kybernetik.com.au so I can see exactly what you're doing?

    @Rusted_Games Yes, you can just make a new MixerTransition2D and set its type to Directional or make a new DirectionalMixerState if you want to set up the state directly.
     
  21. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135

    The thing is that the Animations list from the MixerTransition2D is readonly, is there another way to change the clips?
     
  22. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The mixerTransition.Animations property is a ref return, meaning you can get and set it.
     
  23. Rusted_Games

    Rusted_Games

    Joined:
    Aug 29, 2010
    Posts:
    135
    Thanks for the reply, indeed it is a UnityEngine.Object array reference, therefore not suitable for what I want to achieve without complicating things having to cast ClipTransitions I already have in the data definition. Instead of having separate clips I will add to the data asset a MixerTransition2D and use the CopyFrom method, that way Designer can still tweak it from the inspector.
     
  24. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    hey, iam trying to create a mixer/blendtree at runtime just as the docs say, but something is wrong?

    upload_2023-4-12_17-35-41.png

    Code (CSharp):
    1.     void SetupBlendTree() {
    2.  
    3.         _MovementMixer = new LinearMixerState
    4.         {
    5.             { _Idle, 0 },
    6.             { _Walk, 0.5f },
    7.             { _Run, 1 },
    8.         };
    9.  
    10.  
    11.         _trickBlendTree = new DirectionalMixerState {
    12.             {_flatTricks._forward, 0, 0.5f },
    13.             {_flatTricks._left, -0.5f, 0 },
    14.             {_flatTricks._center, 0, 0 },
    15.             {_flatTricks._right, 0.5f, 0 },
    16.             {_flatTricks.backwards, 0, -0.5f },
    17.         };
    18.    
    19.     }
    i even copied your snippet from the docs and it says:

    error CS1061: 'LinearMixerState' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'LinearMixerState' could be found (are you missing a using directive or an assembly reference?)
     
  25. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Are you using the latest version of Animancer? That syntax was only implemented in Animancer v7.4.

    Also, for the directional mixer you'll need to use
    { clip, new Vector2(x, y) }
    rather than just
    { clip, x, y }
    .
     
  26. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    yeah, you are right, i am still on 7.2 - tome for an upgrade :D

    used the old way, fine for now.

    Code (CSharp):
    1.  
    2. _trickBlendTree = new DirectionalMixerState();
    3.         _trickBlendTree.Initialize(5);
    4.         _trickBlendTree.CreateChild(0, _flatTricks[i]._forward, new Vector2(0, 0.5f));
    5.         _trickBlendTree.CreateChild(1, _flatTricks[i]._left, new Vector2(-0.5f, 0));
    6.         _trickBlendTree.CreateChild(2, _flatTricks[i]._center, new Vector2(0, 0));
    7.         _trickBlendTree.CreateChild(3, _flatTricks[i]._right, new Vector2(0.5f, 0));
    8.         _trickBlendTree.CreateChild(4, _flatTricks[i]._backwards, new Vector2(0, -0.5f));
    but ive got another problem, i need to feed the _trickBlendTree into a code that is using a MixerTransition2DAsset, not a DirectionalMixerState.

    so this is what comes next:

    Code (CSharp):
    1.  
    2. PlayAnimation(_manualLandFront, _enterTransitionSpeed, 1);
    3.  QueNextAnimationMixer(_trickBlendTree, _loopTransitionSpeed, 0);
    4.  
    Code (CSharp):
    1.  
    2. void QueNextAnimationMixer(MixerTransition2DAsset mixer, float transition, int priority) {
    3.         _skaterAnimation.QueNextAnimation(null, transition, 1, 100, false, false, priority, mixer);
    4.     }
    so either

    A) there is a way to convert the DirectionalMixerState to a MixerTransition2DAsset?

    or

    B) can i somehow, fill these (empty) fields

    View attachment 1227426

    with my animation clips at runtime:

    View attachment 1227429

    both solutions would be perfectly fine
     
    Last edited: Apr 14, 2023
  27. SentientSupper

    SentientSupper

    Joined:
    Dec 29, 2022
    Posts:
    3
    How would I clone an object playing an animation during runtime and have the clone be playing the same animations as the original with the exact same times and transitions (and pretty much be an exact clone)?
     
  28. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @RobertOne

    A) No.

    B) Yes.
    asset.Transition.Animations
    is the array of clips so you can just fill that before you play the transition. If you've already played the transition, you'll need to modify the created state directly because modifying the transition after that won't rebuild the state.

    @SentientSupper I've never tried anything like that, but
    foreach (var state in animancerComponent.Layers[x])
    would let you iterate through every state on a given layer and
    state.Clone()
    would give you a copy which you should then be able to play on your second object. You'll probably also want to skip any states where
    state.Weight == 0
    since that means they aren't currently affecting the output so cloning them would probably be unnecessary.
     
    SentientSupper and RobertOne like this.
  29. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    thanks, doyou maybe have an example? :)

    like this is the one i wanna put into the first field with these parameters:
    Code (CSharp):
    1. _flatTricks[i]._forward, new Vector2(0, 0.5f)
    but iam just kinda stuck here
    Code (CSharp):
    1.  _dummyTrickBlendTree.Transition.Animations
    and not really sure how to add the animation with the paremeters now.

    thanks again!

    edit: i think i almost got it:

    Code (CSharp):
    1.  AnimationClip[] newAnimations = { _flatTricks[i]._forward, _flatTricks[i]._left, _flatTricks[i]._center, _flatTricks[i]._right, _flatTricks[i]._backwards };
    2.         UnityEngine.Object[] newAnimationsAsObjects = newAnimations.Cast<UnityEngine.Object>().ToArray();
    3.         _dummyTrickBlendTree.Transition.Animations = newAnimationsAsObjects;
    no need to answer, it works like that :)
     
    Last edited: Apr 13, 2023
  30. SentientSupper

    SentientSupper

    Joined:
    Dec 29, 2022
    Posts:
    3
    Doesn't seem to be working as intended. What I am doing now is getting every state in the layers of the original object and calling
    animancerComponent.Layers[x].Play(state.Clone())
    on the cloned object. This causes the states to be played from the very start. Animancer events on the cloned object also don't work. I don't seem to be able to set the states of a layer directly without calling Play().

    Edit: I've decided to see if I could clone the layer itself directly. I see that AnimancerLayer has ICopyable, but I am unable to call CopyFrom. Ideally I should be able to do something like
    clonedobject.animancerComponent = originalobject.animancerComponent.Clone()
    or make a snapshot of all the data inside the original animancercomponent and load it into the cloned one.
     
    Last edited: Apr 13, 2023
  31. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @RobertOne If you just make the array as
    UnityEngine.Object[]
    you wouldn't need to cast it.

    To modify the structure, you need to either modify the state instead of the transition or destroy the old state before playing the transition again (which will create another state with the new structure).

    @SentientSupper I'm not sure what's wrong, but I should have time to look into it over the weekend.
     
    SentientSupper likes this.
  32. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    How would you que a bunch of animations?
    In mecanim you could just start the first animation, connect the next with an arrow, define the exit time, then connect the next animation etc.

    how would you do the same way in animancer? Lets say i have 3 animations and i wanna play them one after another and after all are finished, go back to the „main“ blendtree
     
  33. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
  34. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @SentientSupper I've added the ability to fully clone all states with a single method, but the necessary changes are too complex to describe here. If you email your Invoice Number to animancer@kybernetik.com.au so I can verify your purchase, I'll send you the updated package.
     
  35. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    38
    Is there a way to break up animation playback by time/frame count?
    I have animations that I want to split among several states, and I want to play them seamlessly from one to the next ie frame 1-7, 7-10, 10-31. I have attack animations that consist of several states (windup, attacking, recovering) and I would like to be able to
    1. Stretch or shrink the animation according to the playback frames (I know it's possible to change the playback speed) and
    2. Play only part of the animation for each step.
    In this way, I plan to design the animations and then just modify them for balance purposes, so I'd need a way to set which frame is the keyframe for the state switch.
    Right now I have six variables: animation frame count for each portion of the animation and functional frame count for how long each of those segments should be played over (as that's how the attack is defined in the code).

    I got animancer pro a few months ago as I know from the lite version that animancer would make my life so much easier, and I'm pretty sure this is very doable, but I was looking through the documentation and it's not super clear to me how.
     
  36. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I can think of a few options:
    • A ClipTransitionSequence would let you play one clip after the other if you split the animation into several clips. Using Timeline to play the clips would also achieve a similar result.
    • Use Animancer Events to mark the segments. The events could change speeds or you could just leave them empty and query their times in a script to decide what to do.
    • Make a custom transition type like the MotionTransition class in the Root Motion Example and give it extra float fields for the timings. I'd probably do that instead of using events.
     
  37. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    38
    Option 3 looks promising, I'll look into that; thanks!
     
  38. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    281
    Hello, all things are good, I only have some problem with prefab workflow.
    Do you know how to remain tpose when saving the prefab?
    I play test animation then before closing prefab mode, I set the rig to Tpose, but when I re-open the prefab it come back to this pose.

    upload_2023-4-21_14-23-7.png
     
  39. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you put it in the T pose then save the prefab, the only reason it wouldn't be in that pose when you re-open it is if something is initializing Animancer so it starts controlling the bones. That's the pose you would see if Animancer is initialized but not playing anything.

    Have a look in the Inspector to see if Animancer is initialized. If it is, go into the AnimancerComponent script and put a log in its InitializePlayable method to see why it's getting called. Otherwise, the only other reason I could think of would be that Unity isn't saving the model in the T pose in the first place.
     
  40. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    281
    that's a great hint, thank you!
     
  41. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    38
    Option 3 worked for me! Thank you!
     
  42. runette_unity

    runette_unity

    Joined:
    Feb 20, 2020
    Posts:
    15
    Hey ho

    I wanted to try this plugin on a very small project of mine.|

    Loaded Animancer Lite 7.4.2 from Asset Store into my 2022.2.1 project.

    All I am getting is

    TypeLoadException: Could not load list of method overrides due to Could not resolve type with token 01000056 from typeref (expected class 'System.Object' in assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') assembly:System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 type:System.Object member:(null)
    Animancer.AnimancerComponent.InitializePlayable () (at Assets/Plugins/Animancer/AnimancerComponent.cs:314)
    Animancer.AnimancerComponent.get_Playable () (at Assets/Plugins/Animancer/AnimancerComponent.cs:77)
    Animancer.AnimancerComponent.Play (UnityEngine.AnimationClip clip) (at Assets/Plugins/Animancer/AnimancerComponent.cs:471)
    Animancer.Examples.Basics.PlayAnimationOnEnable.OnEnable () (at Assets/Plugins/Animancer/Examples/01 Basics/01 Quick Play/PlayAnimationOnEnable.cs:30)
     
  43. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Re-downloadingand re-importing Animancer in the Package Manager should fix it. API changes in Unity versions mean that Animancer needs several different versions and Unity will pick the correct one when you first download it, but then if you change to a different version of Unity it will still let you import the version of Animancer you already downloaded and cause problems whenever it hits one of the changed APIs.
     
  44. runette_unity

    runette_unity

    Joined:
    Feb 20, 2020
    Posts:
    15
    Yes, but then again no :(

    I know you are on the right track - but it still fails.

    Steps to reproduce :

    1 Download Unity Editor 2022.2.17f1
    2 Create new test project from the HDRP Sample Template
    3 Re-download Animancer Asset Package from inside the project (note at this point the package says compatible with 2019 +)
    4 Install the package

    Note - after install the package says compatible with 2023.1.0 + (which is still in beta) !!
     
  45. runette_unity

    runette_unity

    Joined:
    Feb 20, 2020
    Posts:
    15
    ... I upgraded my little test project to 2023.1 beta and it is now working.

    Ok for the test project but ...

    I am wondering if there is a problem in the version setups in the Asset Store - but I am no expert.
     
  46. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I just downloaded Unity 2022.2.17 and followed those steps but didn't get any errors from Animancer and the animation played fine.

    Did you download it in 2023.1 before trying 2022.2 ? Maybe it doesn't want to delete the newer version when re-downloading. Try deleting the package from your AppData folder first: C:\Users\YourUserName\AppData\Roaming\Unity\Asset Store-5.x\Kybernetik\ScriptingAnimation

    There isn't really anything to set up for versions in the Asset Store, it's literally just "I uploaded it in Unity X so it's compatible with Unity X or higher" and when you download it will automatically pick the highest compatible version for you.
     
  47. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    281
    Hello, I have a very involved problem about animation + ragdoll with Animancer.
    So when my character die and revived, the ragdoll at death point takes over the animation, and make bones's rotation differ from their original rotations.
    The problem can be no more if the animation designer keyed all their bones, but in this example, the publisher Dungeon Mason usually not do that. So character after ragdoll state can't go back to their original rotation.

    Because of this, I made a script to lerp back some bones that I know do not has keyframes to their original state on demand (when character is out of ragdoll state / or revive), but it can't work with Animancer, Animancer somehow remember the state of rotation of the ragdoll, but not able with my script.
    Hope to get some idea about this. Thank you.

     
  48. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Don't disable the Animator component, just call
    animancerComponent.Playable.PauseGraph();
     
  49. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    281
    Thank you, I tried PauseGraph > Set rotation > UnPauseGraph. But the rotation still be like when they're not set.
    I even try StopGraph, still same result.
    I can only then change the rotation if I use DestroyGraph, this is good for when player revive, but I don't know if this operation is costly if we call many times during battle ? because ragdoll also be used for onHit for procedural hit animation.
     
  50. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Pausing and unpausing shouldn't affect things like that. Can you send a minimal reproduction project to animancer@kybernetik.com.au so I can take a look?