Search Unity

Animancer - Less Animator Controller, More Animator Control

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

  1. sherzhen

    sherzhen

    Joined:
    Jun 28, 2015
    Posts:
    13
    Hey!
    First of all, I would like to thank you for such a useful and convenient asset, which saved me a lot of time.
    I would like to ask about the following point: I made a root motion animation in umotion, but in the animation window and transition preview, the animation looks different. As if the axes were messed up. Can I do something about this?


    P.S. The animation is also broken in the game.
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Try it in a regular Animator Controller. I expect it would be broken there too because that sort of thing isn't touched by Animancer, it's all handled by the underlying Playables API.

    It could be some sort of avatar configuration issue, but that wouldn't explain how the Animation window can give a different result to my preview window.

    Maybe it's something to do with the character's hierarchy. Try dragging in a new copy of the model, adding your component, and previewing the animation on that.
     
  3. MSavioti

    MSavioti

    Joined:
    Dec 27, 2017
    Posts:
    4
    Hi @Kybernetik

    I have a problem where the Animancer is not recognized inside VS Code.

    upload_2021-2-4_12-48-2.png
    *The type or namespace name could not be found.

    The problem persists in other projects and even in empty ones. The funny fact is that the code compiles successfully, but as I can't use Intellisense to get a better view o what I can do, among other problems.

    Do you have any insight on this matter? Thanks!

    Obs.: I've included the
    Code (CSharp):
    1. using Animancer;
    already.
     
  4. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Hi, @Kybernetik! I have a question related to ClipState.Transition in a custom Editor.
    I previously had an AnimationClip custom editor field like this:
    Code (CSharp):
    1. AnimationClip animation = EditorGUILayout.ObjectField("Animation", animation, typeof(AnimationClip), true) as AnimationClip;
    Now, I converted most of my AnimationClip references in my codebase to ClipState.Transition. But I can't simply convert this custom editor field like this, it doesn't work:
    Code (CSharp):
    1. ClipState.Transition transition = EditorGUILayout.ObjectField("Transition", transition, typeof(ClipState.Transition), true) as ClipState.Transition;
    I guess ObjectField doesn't work with ClipState.Transition.
    What would be the correct way to add this custom editor field?
     
    Last edited: Feb 4, 2021
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @MSavioti A few other people have reported the same issue, but I don't think there's anything I can do about it since there's nothing actually wrong with Animancer's code (otherwise it wouldn't compile).

    For starters, if you could report a Unity bug via the help menu that would be great, then there are a few things you could try:
    @andreiagmu EditorGUILayout.PropertyField will draw it using the correct PropertyDrawer for the given transition.
     
    MSavioti and andreiagmu like this.
  6. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Thanks for the tip, I understand I could normally use EditorGUILayout.PropertyField in a standard CustomEditor.

    My setup is more complex, this custom field I'm trying to convert is from an external asset (Rex Engine).
    It's a bit complicated to explain, but there's a main [CustomEditor] script with an OnInspectorGUI() call, that calls a custom virtual method DrawInspectorGUI(), which is overriden in some other classes.

    This DrawInspectorGUI() draws some custom fields (for each of those other classes) in the inspector using some EditorGUILayout functions, like ObjectField, EnumPopup, LabelField...

    But the issue is that those other classes that override DrawInspectorGUI() aren't really [CustomEditor] classes.
    So, I can't access the "serializedObject" reference that's included with CustomEditor, and then I'm unable to call
    serializedObject.FindProperty("animationProp") and use a SerializedProperty (for EditorGUILayout.PropertyField).

    Is there another way to draw the ClipState.Transition, that doesn't need to be called from inside a CustomEditor?
     
    Last edited: Feb 4, 2021
  7. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You can make your own
    new SerializedObject(target)
    to get the property from.

    Otherwise you would need to find which of my property drawers is used for that transition type, call its GetHeight method, allocate a GUI layout rect of that size, then call the drawer's main GUI function.
     
    andreiagmu likes this.
  8. Andres_Rueda

    Andres_Rueda

    Joined:
    Sep 12, 2018
    Posts:
    1
    Hey! we've beeen testing Animancer as an option to replacing Mecanim since it's so convinient ! but with a simple test with 150 skinned meshed characters we're seeing that Animancer is taking performance spikes wheen changing animations, this is the garbage collection being called, is it being called inside Animancer?
    we're testing on Android, mainly our low end devices, thanks! :D
     

    Attached Files:

    Last edited: Feb 5, 2021
  9. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Both of those PrepareFrame methods are part of Animancer, but I can't see the garbage allocation in that screenshot. Which methods is it actually showing the allocation on?

    Also, keep in mind that the Profiler can't show garbage collection itself. "GC Alloc" is the allocation of memory that will need to be garbage collected at some point, but that will often only be when the character is destroyed such as when unloading the scene so it doesn't necessarily indicate an immediate performance cost.
     
  10. holdingjason

    holdingjason

    Joined:
    Nov 14, 2012
    Posts:
    135
    UPDATE: HAHA Avatar mask is just a text file so added new nodes to it and bam worked totally fine. Great job on making that easy to mess with. THANKS!

    Hi great product. We have a kind of odd situation with Avatar Masks that I want to see if I can figure out.

    So we manually are adding a point to the skeleton that we manipulate via animations that is not in the avatar or original model. We are apply a mask that includes the parents of that point but the animation is now ignoring that point when the mask is applied. My guess because Animancer does not see it in the avatar mask so its been excluded or ignored. Is there someway to manually add it into the mask via something like AddTransformPath etc?

    Thanks
     
    Last edited: Feb 10, 2021
  11. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Animancer doesn't handle any of the Avatar Mask logic, it's all done by the underlying Playables API.

    I suspect the intended solution would be to just add that bone to the original model so editing the mask as a text file could well be the only way around it.
     
  12. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    I have a question related to those earlier posts:

    I have a LinearMixerState.Transition with some locomotion animations (Idle, Walk, Run, Sprint). What's the correct way to add events (preferably Animancer Events) to those animations, and make them trigger at the right times? (when the character's foot touches the ground)

    I'm placing the Animancer Events via the Transition Preview window (that's such a timesaver!). But if I place the events while my Mixer Parameter is at a value (let's say, the threshold for the Walk animation), okay, I can place my 2 footstep events when the foot touches the ground (while previewing the Walk animation).
    But if I change the parameter to the threshold for the Run animation, then the events I placed before obviously don't match with the Run animation footsteps anymore.

    Should I put multiple (more than 2) Animancer events in this Mixer? Is there any other (simpler) solution?
    Or should I use Unity's Animation Events in each separate animation, for that case?
     
  13. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The Synchronisation system will automatically make the animation loops line up even if they are different lengths. If they start at different parts of the walk cycle, you can set the Cycle Offset in the animation import settings to correct them so they all start at the same place so that the synchronisation will correctly line up their corresponding poses. So if you make them all start with the right foot down, you could have an event on the mixer at normalized time 0 and another at 0.5 which should be correct for any parameter value (except below the walk threshold since you won't want footstep sounds while Idle).

    But as I mentioned in another thread (which I can see you liked) I would make a system based on the Y positions of the feet and integrate it with my foot IK to give a more physically accurate result without needing to set up as many events on every character.
     
    andreiagmu likes this.
  14. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Oh yes, I'd just found that other thread some minutes ago, hehe
    Anyway, thank you for the Cycle Offset tip! :D
     
  15. Artheus

    Artheus

    Joined:
    Aug 29, 2013
    Posts:
    9
    Hey, just started using Animancer and I'm converting my animations now. I have a question about best practices. Currently, I'm converting the movement animations and I have 3 modes depending the type of weapon equipped. Unarmed, handgun, and long gun. Whats the best way to convert these to Animancer? Keep in mind, the player is expected to change weapons frequently during gameplay.
    • Should I make one type of movement component with 3 MixerState.Transition2D fields, and play the one that is relevant?
    • Or is it better to make one one parent component and 3 separate child components with one MixerState.Transition2D in each one? Then attach all 3 components to the relevant game object.
    • Is it also possible to replace the States array in a Mixerstate during runtime (replace the current set of animations with a different set)? Is that a good idea?
    • If an animation clip/state is referenced in a scene, is it initialized and ready to play or does it load it on request?
    • Lets say I follow your Weapons example to set up my animation structure and two weapons share the same animation type, in this case long gun. Does that mean two identical set of animations are loaded or are they just references?
     
    Last edited: Feb 15, 2021
  16. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    1. I generally recommend splitting things into multiple components.
    2. That's probably the approach I'd go for.
    3. Replacing the states in a mixer is possible, but unless you're really low on RAM you'd be better off just having several different mixers instead of wasting CPU time on the swap.
    4. They're just references, otherwise every character would have their own copy of each animation.
     
  17. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    What am i doing wrong if additive animations don't want to work?
     
  18. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I can't see any reason for it to act like that, though I've never actually done any work with additive animations.

    It might be a Unity bug since all Animancer does it tell the layer mixer that a particular layer should be additive and the Playables API takes care of the rest.

    Can you send a minimal reproduction project to animancer@kybernetik.com.au so I can take a look at it?
     
  19. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    @Kybernetik Hi, I have another question: (btw, I'm using Animancer Pro v6.0)

    I'm working with 2D sprite animations (using ClipState.Transition), let's say I have a quick animation with 3 sprite frames.
    I use Fade Duration = 0, for instant transitions between animations.
    I can change the animation frame rate normally via the Transition's Speed parameter, to make it faster or slower.

    But no matter what value I set those parameters, the animation's MaximumDuration is always 1 (second).
    Is this normal behaviour? I'd expect MaximumDuration value to change, based on the transition's Speed value.

    I want to play a second animation (and do some other stuff) after my first one ends. For now, I have a coroutine that awaits for a duration value (it's part of the logic of an external asset).

    I was setting this duration to the transition's MaximumDuration (that's always 1 second).
    But then, my first animation either doesn't complete before the 1 second (if Speed is low), or the first animation completes but freezes until the 1 second (if Speed is high).

    Is there a better way to get the correct duration of my animation?
     
    Last edited: Feb 19, 2021
  20. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    MaximumDuration is only used in the editor to determine how the event timeline gets drawn, it's not really meant for anything else.

    If you only need that value when you actually play it, you can use the state's Duration or RemainingDuration.

    Otherwise you can calculate it from the transition with
    transition.Clip.length * transition.Speed
     
    andreiagmu likes this.
  21. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    I get this warning in playmode:
    "Possible Bug Detected: The AnimancerEvent.Sequence.OnEnd callback being invoked contains multiple delegates using the same method with different targets.[...]" when i add an event via the inspector to a transition (somewhere in the middle after the fade-in) that is played in an additive layer (not sure if that's relevant). In code i use the OnEnd event to fade out the state

    Code (CSharp):
    1. landingState.Events.OnEnd += () => { landingState.StartFade(0, 0.1f); };
    The inspector added event only calls a single defined method that is different.
    I enabled/use UltEvents through the PlayerSettings define.
    upload_2021-2-20_14-43-49.png
    What could be the problem?

    Edit: using OnEnd assignment (=) instead of addition (+=) gets rid of it. It seems they don't get cleared properly, even though i add them after Play():

    Code (CSharp):
    1. if (landing.Clip != null)
    2. {
    3.     var landingState = additiveLayer.Play(landing);
    4.     landingState.Events.OnEnd += () => { landingState.StartFade(0, 0.1f); };
    5. }
     
    Last edited: Feb 20, 2021
  22. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Transitions store their own event list and give it directly to the state they play, so even after you play something else which removes the state's events, any modifications will still be retained by the transition.
     
  23. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    If i understand you correctly there are two possible unexpected scenarios:
    Either the eventlist from the transition is passed as reference which means by modifying the events of the state i'm modifying something i'm not expecting to touch (the transition, where i then stack event additions);
    Or the empty/unset OnEnd event from the transition is still considered as valid when i try to assign one from code (like an empty container, but still a container) - so there are two at the point of assignment (empty+dynamicly added, where they are considered duplicates)
    In both cases i would expect a different outcome. If one of those applies, hopefully it can be improved in some way
     
    Last edited: Feb 21, 2021
  24. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That's correct.

    animancer.Play(clip)
    gives you a state without any events so if you access the Events property it gets a new one from the object pool. Then when you play something else, the events are cleared and returned to the object pool.

    But since transitions already have their own event sequence,
    animancer.Play(transition)
    just assigns it directly to the state. Then when you play something else, the state just drops its reference to the transition's events but doesn't clear or pool them (since that would remove any events you set up in the Inspector).

    There are a few different ways I could have designed it, but I decided to instead implement that warning because assigning delegates creates garbage if you don't cache them. So rather than creating garbage every time you play the transition, you should just set up the events once on startup which avoids the problem entirely.
     
  25. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    Good to know, because the warning is not very helpful in describing why that happens. I see the value in not creating garbage; the sideffect though is that events set in the editor then conflict with the ones set in code even though they should not from expectation. Without having looked at the source code shouldn't it be possible by having a pooled event container that just receives references to each event set in the editor, instead of having to copy the whole container, thus not creating garbage, while still allowing runtime modifications? I think it would be beneficial to be able to use both runtime and edit-time events together.
     
    Last edited: Feb 21, 2021
  26. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You can use both runtime and edit-time events together, just set up the runtime events in the transition on startup instead of adding them to the state every time you play it.

    Otherwise every transition you play would need to copy the contents of the transition's event sequence into one retrieved from the pool. That wouldn't need to create garbage but would still be less efficient for everyone and it wouldn't help anything when you don't need to modify the events or when you set up the events on startup. The only case it would help is if you're modifying the events after they've been assigned to the state, but I don't see much value in improving a use case that creates garbage when there's already a better alternative.

    I'll see if I can improve the warning message though.
     
    Flavelius likes this.
  27. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    175
    Thanks for the tips!
    Based on AnimancerState.Duration's return value, I guess that "calculation from the transition" should be like this instead?
    transition.Clip.length / Math.Abs(transition.Speed)
     
  28. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Yeah, that's right.
     
  29. weto4ka

    weto4ka

    Joined:
    Feb 8, 2019
    Posts:
    48
    Hey! I'm new to Animancer Mixer and I need help)
    I want to change the animator mixer on the certan layer at runtime (add / remove animations from it). But I didn't understand how to do it. When starting the scene, the Animancer Manual mixer sets the predefined values, and then when I try to change it, I get an error like this:
    upload_2021-3-1_22-31-19.png
    I don't know how to add new childrenStates to the layer that I want. I try to do it like that:
    Code (CSharp):
    1. private ManualMixerState CreateMixerState(AnimancerComponent _animancer, SeqInfo seqInfo)
    2.     {
    3.         ManualMixerState mixerState = new ManualMixerState();
    4.         mixerState.SetRoot(_animancer);
    5.         if (seqInfo.clipTimePairs != null)
    6.         {
    7.             if(mixerState == null)
    8.             mixerState.Initialise(seqInfo.clipTimePairs.Count);
    9.             else if(seqInfo.clipTimePairs.Count > mixerState.ChildCount){
    10.                
    11.                 mixerState.Destroy();
    12.                 mixerState.Initialise(seqInfo.clipTimePairs.Count);
    13.  
    14.             }
    15.          
    16.             Debug.Log("Mixer Child: " + mixerState.ChildCount);
    17.             for (int i = 0; i < mixerState.ChildCount; i++)
    18.             {              
    19.                 var item = mixerState.CreateChild(i, seqInfo.clipTimePairs[i].clip);
    20.                 item.Weight = 1f / mixerState.ChildCount;
    21.                 item.Speed = seqInfo.clipTimePairs[i].normalTime;
    22.                 seqInfo.clipTimePairs[i].normalWeight = item.Weight;
    23.                 clipTimes.Add(item, seqInfo.clipTimePairs[i]);            
    24.  
    25.             }
    26.         }
    27.  
    28.         mixerState.DontSynchroniseChildren();
    29.         return mixerState;
    30.     }
    Could you plaese, help me?
     
  30. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You must be calling Initialise with a child count of 1 or 0 (or a negative number) which would give you a mixer that doesn't actually have anything to mix, hence the warning. Try logging the value you're passing into Initialise.
     
    weto4ka likes this.
  31. weto4ka

    weto4ka

    Joined:
    Feb 8, 2019
    Posts:
    48
    oh, yes, thanks) there is value 1 was)
    and I have another question. Animation was added in mixer state, and for State speed is 1, but for animations that in state it's 0 for some reason. And only base layer is playing
    upload_2021-3-2_14-55-57.png
    How I can set speed for clips in the state? Because for me it seem like I set it in the code (my post above), but actually time still 0 and mixed animations aren't playing when added
     
  32. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You're setting
    item.Speed = seqInfo.clipTimePairs[i].normalTime;
    . Is that right?
     
  33. weto4ka

    weto4ka

    Joined:
    Feb 8, 2019
    Posts:
    48
    yes, thanks,I just changed it to 1, now it works)
    Can amount of ChildStates in ManualMixerState be changed on runtime? like if it's initialized with 3 elements (they already exists in it), but on runtime I want to change amount of childs (reduce/increase).For example add 4th or remove 2d element in that mixer. How could I do that?
     
  34. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You can call Initialise again to change the child count, but that won't be very efficient.

    Since it's a manual mixer, you're likely better off just creating all the child states you might need or just having multiple mixers which you swap between as necessary.
     
    weto4ka likes this.
  35. JustAKgiDev

    JustAKgiDev

    Joined:
    Jul 6, 2013
    Posts:
    13
    Hey, I sent an email 3 - 4 days ago and I haven't heard back. Any chance you could whenever you have time? Thanks!
     
  36. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Hi all — I'm trying to have "manual" control over the hands (I have my own hand-posing routine that makes them properly grip whatever object they're holding). But I'm running into trouble because whenever AnimatorController and Animancer are playing an animation, my attempts to pose the hands is overridden by the animation.

    I know that in principle I could move my posing into LateUpdate and it should run after the animation, but this is causing me grief in other ways. I thought perhaps I could use an AvatarMask to tell the animation system to quit screwing with the hands at all.

    I created an AvatarMask, and masked out the hands both in the Humanoid section, and in the transform section:

    Screen Shot 2021-03-09 at 2.04.24 PM.png
    (Transform section not shown but trust me, I did that too.) Then I had my play script use it like so:

    Code (CSharp):
    1.         if (anim == null) anim = GetComponent<AnimancerComponent>();
    2.         var state = anim.Play(animation);
    3.         state.Time = startTime;
    4.         if (avatarMask != null) anim.Layers[0].SetMask(avatarMask);
    And you can see, at runtime, it seems to be applied:
    Screen Shot 2021-03-09 at 2.03.58 PM.png

    Yet I still can't pose the fingers. For example, if I simply find a finger bone in the Hierarchy view and try to rotate it using the Unity inspector or rotation tool, I am unable to rotate it at all while the animation is playing.

    The docs only mention using AvatarMask with layered animations, which is not my intent — I have only one animation, and I just want it to leave the hands alone. Is there a better approach? Or, if this approach should work, are there common gotchas I could check for?
     
  37. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    @sizzle3003 I just replied to an email that was in my spam folder. please let me know if that was you.

    @JoeStrout Can you just remove the hands from your character's Avatar Definition so the animation system doesn't touch them at all? Otherwise I think you'll have to use LateUpdate because Humanoid Rigs always write to all their bones and won't blend with anything else.
     
  38. unity_rFuPAqTZJykZ_A

    unity_rFuPAqTZJykZ_A

    Joined:
    Sep 15, 2020
    Posts:
    4
    Hello @Kybernetik
    First, thank you for this asset, it's been wonderful so far !

    I've got a question regarding the use of ClipStates.Transitions. I'm having an ability system in my game, there is one scriptableObject for each ability (the scriptable object contains the animations to play, the effects of the ability and some other stuff), and when adding an ability to a creature, my system automatically add the corresponding creature state at runtime.
    So basically, all creatures can have all abilities, however i think i'm having an issue. If they all share the same ability scriptableObject reference, it means they all share the sames ClipState.Transition, and I think this is wrong, right ? (cause they will share the same ClipState.Transition.State)?

    Is there any workaround for this? Should I deep copy the Transition and then use it ?
    Unfortunatly, so far I'm using animancer lite (I'll get the pro version very soon), I can't access the source code and cannot figure out how do it, it would be really nice if you can explain me !
    Thanks !
     
    Last edited: Mar 10, 2021
  39. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Each character will create their own state. The description of transition.State explains that it's only a reference to the most recently played state.

    The only time sharing transitions really complicates things is if you're using Animancer Events (which are Pro-only), but the Shared Event Sequences section explains how to deal with that.
     
  40. unity_rFuPAqTZJykZ_A

    unity_rFuPAqTZJykZ_A

    Joined:
    Sep 15, 2020
    Posts:
    4
    Thank you for this super quick answer.
    I was following the weapons example, https://kybernetik.com.au/animancer/docs/examples/fsm/weapons/, and the exemple was using the transition.state in order to know if the animation was still playing and decides if it should restart the combo or not. But I should be able to workaround by just storing the state returned by Play(Clip);
    Also thanks for the insights about animancer events
     
  41. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    The Weapon class is a MonoBehaviour attached to the weapon model, so each character will get their own copy of the script (and therefore separate transitions) when the weapon is instantiated.
     
  42. b1gry4n

    b1gry4n

    Joined:
    Sep 11, 2013
    Posts:
    146
    Not sure if I am approaching this the correct way but I am having a sync issue when using override layers. My setup is as follows:

    Layer 0 : Base movement (Directional mixer animations)
    Layer 1 : Additive leaning animations (parameter input based on current acceleration/velocity)
    Layer 2 : Right arm override layer (right arm avatar mask)
    Layer 3 : Left arm override layer (left arm avatar mask)

    My character is able to equip items in its left and right hand. Sometimes you could have only an item in left, sometimes only right, sometimes both. Ive created identical, but slightly modified, animations for the weapon types. example : 45 degree run, 45 degree run with sword and shield. I want to use an override layer to layer the weapon on the base animations. This is all working for the most part except my issue is with the layers not being in sync. Is there a way to sync a layers time to another layer? The way the additive layer syncs over other layers is what I want, but I want to be able to sync using an override layer.

    Here is a video showing the problem:

     
  43. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You should be able to just set the normalized time of the new animation whenever you play it to match the normalized time of the base animation. Then if they both have the same speed and length they should stay in sync. Or if they don't have the same speed and length, then you'd need to set the time every frame to keep them in sync.
     
  44. b1gry4n

    b1gry4n

    Joined:
    Sep 11, 2013
    Posts:
    146
    Ahh thank you for pointing me in the right direction. I was setting the normalized time when i would initiate the mixer to play, but I was not setting the normalized time after changing the weight, since the weight is going from 0-1 multiple times as you equip/unequip. Its working now by syncing the normalized time every time i adjust the weight.

    Code (CSharp):
    1.         public void SetArmWeight(int arm, bool enable)
    2.         {
    3.             if (arm == 1)
    4.             {
    5.                 animancer.Layers[rightArm].Weight = enable ? 1 : 0;
    6.                 if (enable)
    7.                 {
    8.                     float desiredTime = animancer.States.GetOrCreate(_Move.GetMoveSet).NormalizedTime;
    9.                     animancer.States.GetOrCreate(rightArmLib.GetMoveSet).NormalizedTime = desiredTime;
    10.                 }
    11.             }
    12.             else if (arm == -1)
    13.             {
    14.                 animancer.Layers[leftArm].Weight = enable ? 1 : 0;
    15.                 if (enable)
    16.                 {
    17.                     float desiredTime = animancer.States.GetOrCreate(_Move.GetMoveSet).NormalizedTime;
    18.                     animancer.States.GetOrCreate(leftArmLib.GetMoveSet).NormalizedTime = desiredTime;
    19.                 }
    20.             }
    21.         }
     
  45. b1gry4n

    b1gry4n

    Joined:
    Sep 11, 2013
    Posts:
    146
    Might be too slow of a response, but I didnt see if you solved your issue. Additive animations in unity arent as straight forward as it seems they should be. In order to have an additive animation work you need to make sure youre importing the animation correctly. Make sure you have "Additive Reference Pose" ticked.


    Youll also need to think about how youre blending this animation. Heres an example...

    I wanted a character to lean into turns as they were walking. The way additive animations work is by calculating the difference between your "pose frame" and the animation itself after the pose frame. I created an animation clip that was only 1 frame long, where frame 0 was a pose close to the walking animation and frame 1 was the lean. Now this animation is ready to be additive. In the image below i have "loop time" checked, but it shouldnt be. For me it gives weird results/stutter. unchecking loop time fixes it.



    In your case with your jump youll want frame 0 to be the fall pose and frame 1 to be the landed/crouched pose. The rest of your setup should work after that.
     
    Flavelius and Kybernetik like this.
  46. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    Yes, thanks for the writeup. I already found that this was my wrong assumption (that the first frame itself already is the delta, when it's actually the difference to the first/reference frame), but it's good to have this confirmed.
     
  47. angrychopin

    angrychopin

    Joined:
    Oct 8, 2018
    Posts:
    2
    Hi there guys,

    First of all, I must say, thank you so much for this plugin, it has single-handedly helped me restore my faith in-game systems design in Unity and also greatly helped our workflow in both animation & state machine behaviours.

    I have a quick question about reusing animation configurations. What's the best process to do so? We end up having to have to configure the same animation and its events (e.g. dodge roll) in Inspector for a bunch of characters. Is there an easy way to copy and paste ClipState information between objects or maybe store it somewhere centrally?
     
  48. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    There are a few ways you could approach that:
    • Animancer doesn't have anything for it, but Inspector Gadgets Pro adds Copy and Paste functions to the context menu for all Inspector fields. You can use it on Animancer Events by Right Clicking on the foldout arrow next to the event timeline.
    • If you right click on the header of your component, Unity has functions to copy and paste the whole component which would get the job done as long as you do it before setting up all your other fields.
    • If you use Transition Assets instead of raw transitions then they'll each be defined in their own individual ScriptableObject assets so you can duplicate them and share them between multiple characters. That can be a bit inconvenient because looking at your script will only show the reference to the transition asset so you have to click on it to select that asset if you want to look at the actual transition, then manually go back to your previous selection (though Inspector Gadgets Pro also has a Nested Inspector feature to avoid that problem).
     
  49. vonSchlank

    vonSchlank

    Joined:
    Jan 5, 2017
    Posts:
    36
    Hello,
    I'm trying to show a given frame of a clip, without playing the clip first, so i created something like this:

    var state = animancer.Play(myAnimationClip);
    state.Speed = 0;
    state.NormalizedTime = 0,5f;

    It shows the pose at the middle of the clip, but root motion is not applied. (Animator's Apply Root Motion is on)
    How can i apply root motion?
     
  50. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Root motion is movement over time throughout the animation so if the animation isn't actually playing then you aren't going to get any root motion.