Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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,485
  2. laja

    laja

    Joined:
    Sep 29, 2022
    Posts:
    11
    By any chance is it possible to change the animation clip speeds individually inside a DirectionalMixerState?
     
  3. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    mixer.GetChild(x).Speed = ...
     
    laja likes this.
  4. laja

    laja

    Joined:
    Sep 29, 2022
    Posts:
    11
    At the end of a jump I am playing the landing animation. However if the player is moving, I'd like to play the running animation. Can I blend these two together somehow? It seems like for the layer functionality I should use Avatar Masks, but here I'd like to play both animation on the same full avatar, just blending them a bit (so the first few steps of the running would be blended with the landing animation). Is that possible?
     
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    Putting both those animations in a Linear Mixer (with sync turned off) would probably get the job done, but might not be the most effective way to do it.

    Something like this might be able to give the result you want:

    Code (CSharp):
    1. private void OnLanding()
    2. {
    3.     var landState = animancer.Play(land, fadeDuration, FadeMode.FromStart);
    4.     var runState = animancer.Play(run, fadeDuration);
    5.  
    6.     var landWeight = 0.5f;
    7.     landState.StartFade(landWeight, fadeDuration);
    8.     runState.StartFade(1 - landWeight, fadeDuration);
    9.  
    10.     landState.Events.OnEnd += () =>
    11.     {
    12.         landState.StartFade(0, fadeDuration);
    13.         runState.StartFade(1, fadeDuration);
    14.     };
    15. }
     
    laja likes this.
  6. laja

    laja

    Joined:
    Sep 29, 2022
    Posts:
    11
    Thanks :) This helped me to make it work. Yay!
     
  7. Weasyv

    Weasyv

    Joined:
    Apr 7, 2021
    Posts:
    4
    Good day!

    I recently purchased Animancer Pro and so far this has been such an awesome tool. I usually build my own animation systems but I ran into a lot of the issues you highlighted in the documentation. Building my own system totally derails my development speed so Animancer is a godsend for me. It's exactly what I wanted to try to build, but far better than I could have built it.

    I do have a quick question about integrating Animancer into my project that uses GitHub for source control. My repo is currently public (I haven't pushed anything with Animancer yet) and I'm wondering how I should manage sharing my code. I work with 2 other developers who haven't purchased Animancer Pro.

    Ideally, I'd like to use Unity's package manager and list Animancer as a dependency in the package.json so other developers that clone the repo are prompted to download Animancer as a dependancy so that I'm not exposing Animancer code in my repo directly. I ran into an issue where adding Animancer through the Unity Package Manager doesn't actually update the manifest.json, so I'm not too sure how I should handle this.

    If there's a standard approach you can point me to or any advice/concerns you have to offer I'd love to know!

    Thank you,
    Weston.
     
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I wish the system worked like that but unfortunately, the package manifest system isn't actually connected to your login details or Asset Store purchases so it doesn't have the ability to automatically download assets you have purchased. And even if it could do that, it also doesn't have the ability to download an alternative package if the main one isn't available (i.e. download Animancer Lite if you haven't purchased Pro).

    If your repo definitely needs to be public, the best solution would probably be to gitignore the Assets/Plugins/Animancer folder so each user will need to download Animancer themselves. Anyone who hasn't purchased Animancer Pro would be able to use Animancer Lite to run everything in the Unity Editor, they just wouldn't be able to make runtime builds if you're using any Pro-only features.
     
  9. Weasyv

    Weasyv

    Joined:
    Apr 7, 2021
    Posts:
    4
    That's too bad. I'm used to using npm which makes working with dependencies much easier.

    I'm a bit new to this, but if each team member has to install animancer manually does that mean they would also need to re-create any references to the animancer script? Or would this resolve itself if the path to the animancer script is the same?

    If I made the repo private would it be okay for me to share the animancer pro code on the project level so other team members could use it without having to install it?

    I would like to eventually automate the build process in a pipeline and I'm worried that having a manual step for installing animancer would cause issues.

    I know my questions aren't specifically related to animancer, but it's the only paid asset I have right now. I really appreciate you taking the time to answer my questions.

    Thanks,
    Weston.
     
  10. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    Yeah, as with many parts of Unity recently the Package Manager ended up being a half assed step towards something truly great.

    Unity tracks asset references using GUIDs rather than file paths but yes, once each user imported Animancer any existing references to Animancer stuff would start working now that the assets they point to actually exist.

    If the repo is private it's fine to just include Animancer Pro. Its License Type is Extension Asset as shown on the store page which means each team member who will actually be interacting with Animancer should buy their own copy.
     
  11. Weasyv

    Weasyv

    Joined:
    Apr 7, 2021
    Posts:
    4
    Hi again. First off, thanks for your responses so far. Second, Animancer is a fantastic product and I am so happy you made it. I love every bit of it. I was worried it would be a bit less visually informative than mechanim (mainly for animation transitions), but boy was I wrong. I love Animancer!

    I do have some (probably dumb) questions regarding the state machine examples you give in the documentation.

    1) In the 3d Game Kit example it takes a bit of time to reverse engineer where certain pieces of logic live. Do you stand by the design choices that were made when building the state machine? LocomotionState, CharacterMovement, and CharacterParameters all depend on each other heavily. Some animation logic exists in the CharacterMovement, while the majority is within LocomationState. Lots of states depend on CharacterMovement, even though some only really need "IsGrounded", which feels like it should be in CharacterParameters. Why is "CheckMotionState" in Character and called many times instead having its logic within the CharacterBrain? I only ask because I built a state machine in my game based on yours and I'd like to know a bit more about the reasons for your design choices.

    2) How do you actually drag states from the "States" gameobject to the "Player" gameobject (for the locomotion and airborne fields in the StateMachine)? I can do it if I lock an inspector window, create a new one, and drag from one to the other, but this feels like a bit of a workaround. Is there a more intuitive way?

    Thanks for all the help!
     
    Kybernetik likes this.
  12. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I might change a few things if I were to do it again, but I'd likely keep the general structure pretty similar, especially when the goal was to mostly replicate the behaviour from the 3D Game Kit for the sake of comparison rather than trying to make an extensible character controller system.

    • Parameters depends on nothing
    • Movement depends on Parameters
    • State depends on Parameters and Movement
    That seems reasonable to me. All those dependencies are one way and the State needs access to all those things to do its job.

    The only contact CharacterMovement has with the animation system is to get the root motion, which seems appropriate to put there.

    Other than that, the only other animation related thing is turning. It can't go in LocomotionState because it's also used by other states (airborne and attack). It could be reasonably separated into a CharacterTurning component to get it out of CharacterMovement though.

    IsGrounded would make sense in CharacterParameters. The only real benefit of having it in CharacterMovement is that the setter can be private which is nice in the example since it's the only system currently setting it, but that might actually be undesirable if you want to do things like have jumping force IsGrounded to false immediately.

    Basically everything that checks IsGrounded also calls UpdateSpeedControl which is a little odd because it's trying to replicate the behaviour of Unity's implementation. It uses some dynamic parameters (MovementDirection, ForwardSpeed, DesiredForwardSpeed) and some fixed stats (MaxSpeed, Acceleration, Deceleration) which don't seem appropriate for the CharacterParameters class.
    It's in Character because that's where the StateMachine is. It takes details from things the Character has (which could be simplified to just the Parameters if IsGrounded is moved there) and controls the StateMachine it owns.

    It's not in CharacterBrain because it's not about the character's intent or goals. Doesn't matter if the character is controlled by player input or AI or nothing at all, if the character was in AirborneState and they become grounded then AirborneState knows it's no longer the right thing for the character to be doing. Similarly, DieState knows it doesn't care about being grounded or which way the brain wants to go so it doesn't call that method.

    If I wanted to avoid needing to call it everywhere, I'd consider giving Character a FixedUpdate method for that. Then it would be up to the individual states to reject any state changes they don't like (which they should already be doing).

    I implemented a feature in Inspector Gadgets which lets you pick which component you want if you drop an object that has multiple of the appropriate type.

    Other than that, if you Right Click the header of a component and go to Properties, it will open a window locked to just that one component. It's a bit more tedious than having a whole second Inspector if you need to do that for multiple components, but with only one it's fast enough.

    Or you can always just put each state on a separate object. It would be unfortunate to waste performance just to get around a minor annoyance in the editor, but it's unlikely to really matter in most cases.
     
  13. termway

    termway

    Joined:
    Jul 5, 2012
    Posts:
    46
    Hi there,

    I'm trying to play an animation on a layer with a mask together with a base layer which play a BlendTree (Float1ControllerTransitionAsset).
    - Layer1 : BaseLayer (Locomotion: BlendTree, No Mask)
    - Layer2 : HitLayer (Mask: Upperbody)

    The problem when I use a BlendTree is that the mask is not used on my other layer (my character's feet move with an upper body mask).

    Here the modified script from the Linear Blending test scene that I use to test my problem:
    Code (CSharp):
    1.   public sealed class LinearBlendTreeLocomotion : MonoBehaviour
    2.     {
    3.         /************************************************************************************************************************/
    4.  
    5.         [SerializeField] private AnimancerComponent _Animancer;
    6.         [SerializeField] private Float1ControllerTransitionAsset.UnShared _Controller;
    7.  
    8.         [SerializeField] ClipTransition _HitTransition;
    9.         [SerializeField] AnimancerLayer _HitLayer;
    10.         [SerializeField] AvatarMask HitMask;
    11.  
    12.         /************************************************************************************************************************/
    13.  
    14.         private void OnEnable()
    15.         {
    16.             _Animancer.Play(_Controller);
    17.             _HitLayer = _Animancer.Layers[1];
    18.             _HitLayer.SetMask(HitMask);
    19.             _HitTransition.Events.OnEnd += () => _HitLayer.StartFade(targetWeight: 0, fadeDuration: 0.5f);
    20.         }
    21.  
    22.         [ContextMenu("Hit")]
    23.         private void Hit()
    24.         {
    25.             _HitLayer.Play(_HitTransition);
    26.         }
    27.  
    28.         /************************************************************************************************************************/
    29.  
    30.         /// <summary>Controlled by a <see cref="UnityEngine.UI.Slider"/>.</summary>
    31.         public float Speed
    32.         {
    33.             get => _Controller.State.Parameter;
    34.             set => _Controller.State.Parameter = value;
    35.         }
    36.  
    37.         /************************************************************************************************************************/
    38.     }
    upload_2023-7-19_15-0-41.png

    Did I miss something obvious?

    It seems, it is working as intended with MixerState, so I will use this in the meantime.

    Code (CSharp):
    1. public sealed class LinearMixerLocomotion : MonoBehaviour
    2.     {
    3.         /************************************************************************************************************************/
    4.  
    5.         [SerializeField] private AnimancerComponent _Animancer;
    6.         [SerializeField] private LinearMixerTransitionAsset.UnShared _Mixer;
    7.  
    8.         [SerializeField] ClipTransition HitTransition;
    9.         [SerializeField] AnimancerLayer HitLayer;
    10.         [SerializeField] AvatarMask HitMask;
    11.  
    12.         /************************************************************************************************************************/
    13.  
    14.         private void OnEnable()
    15.         {
    16.             _Animancer.Play(_Mixer);
    17.             HitLayer = _Animancer.Layers[1];
    18.             HitLayer.SetMask(HitMask);
    19.  
    20.             HitTransition.Events.OnEnd += () => HitLayer.StartFade(targetWeight: 0, fadeDuration: 0.5f);
    21.         }
    22.  
    23.  
    24.         [ContextMenu("Hit")]
    25.         private void Hit()
    26.         {
    27.             HitLayer.Play(HitTransition);
    28.         }
    29.  
    30.  
    31.         /************************************************************************************************************************/
    32.  
    33.         /// <summary>Controlled by a <see cref="UnityEngine.UI.Slider"/>.</summary>
    34.         public float Speed
    35.         {
    36.             get => _Mixer.State.Parameter;
    37.             set => _Mixer.State.Parameter = value;
    38.         }
    39.  
    40.         /************************************************************************************************************************/
    41.     }
     
    Last edited: Jul 19, 2023
  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    It looks like it's caused by the Animator Controller even if you just have it playing a single regular state instead of a Blend Tree. Unfortunately, that's a Unity bug and Animancer can't do anything about it because all the actual blending and masking is handled internally by the Playables API. It's just one of the weird things that happens because Animator Controllers weren't properly designed to be used as part of another system.
     
  15. Weasyv

    Weasyv

    Joined:
    Apr 7, 2021
    Posts:
    4
    Wow, I really appreciate you taking the time to give an in depth response for each of my questions. You made some excellent points. Thanks for clearing up my confusion and giving insight into your decisions. Your response has helped me immensely with my project's structure.

    Thanks again for everything you've done!
     
  16. echba11h

    echba11h

    Joined:
    Sep 25, 2022
    Posts:
    4
    When using HybridAnimancer, normally I just need to call Animancer.Play(StateName) to switch between animator states. But when switching from animancer to animator, if I don't specify normalizedTime the animator controller will be stuck in default state forever.

    Code (CSharp):
    1. private HybridAnimancerComponent _hybridAni;
    2.  
    3. private readonly int _state1Hash = Animator.StringToHash("State1"); //Default state
    4. private readonly int _state2Hash = Animator.StringToHash("State2");
    5. private AnimationClip _clip;
    6.  
    7. private void Test()
    8. {
    9.    _hybridAni.Play(_state1Hash); //It worked normally
    10.    _hybridAni.Play(_state2Hash); //It worked normally
    11.    _hybridAni.Play(_clip);
    12.    _hybridAni.Play(_state2Hash); //will stuck at State1 if I don't specify normalizedTime.
    13.    _hybridAni.Play(_state2Hash, 0, 0); //will work normally
    14.  
    15.  
    16. }
    As I understand, the default value of normalizedTime is -infinity but I don't really understand why it works normally when not switching to animancer.
     
  17. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I have no idea why specifying the time would avoid the issue, but it's most likely caused by the fact that Animator Controllers don't properly handle multiple Play calls in the same frame and by default when Animancer stops an Animator Controller it will tell it to play the default state right before disconnecting it from the Playable Graph, meaning it still counts as the same frame whenever you tell it to play again and it gets reconnected.

    Try setting the Actions on Stop to Continue instead of Default State (in the Controller field of the HybridAnimancerComponent). It has a tooltip explaining how it works.
     
    echba11h likes this.
  18. manurocker95

    manurocker95

    Joined:
    Jun 14, 2016
    Posts:
    191
    @Kybernetik any way to sync the animation frame between 2 HybridAnimancerComponent (with same animationclip)?

    I tried retreiving the normalized time from the first object-> after play in the second-> set normalized time. But doesn't work. Same happens with normalizedTime % 1, and Time.

    Any idea?
     
  19. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    Try calling Play directly on the second one since it can take a normalized time. That's actually what the state's NormalizedTime property does because Animator Controllers don't have a way to just set it directly. The only reason I know of that it wouldn't work is if something else is also calling Play on it in the same frame because Animator Controllers don't support that.
     
  20. manurocker95

    manurocker95

    Joined:
    Jun 14, 2016
    Posts:
    191
    Animator components are empty of controllers, so animancer is controlling the whole thing. I can't see any Play method with a normalizedTime parameter. Just the fade duration....

    Btw, I tried calling just "Play" and then setting the NormalizedTime and it doesn't work either.
     
  21. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    HybridAnimancerComponent has several Play methods with a normalizedTime parameter.
     
  22. manurocker95

    manurocker95

    Joined:
    Jun 14, 2016
    Posts:
    191
    I was looking at NamedAnimancerComponent, my bad. Okay, found the issue. No idea why States.TryGet(_stateKey, out var state) was returning false (as if the state key didn't exist in the dictionary even if it should) and I had a null check to return 0 in that case. Saving the current state on play and returning the normalized time, synced the animations properly. Sorry for the inconveniences. It had nothing to do with the normalized time set.
     
    Last edited: Jul 26, 2023
  23. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    348
    I have an animation (which only controls the character's arms) that I put in Layer 1 and from time to time I fade it in and fade out somewhat later; so Layer 1 has either one State active or none.

    I noticed that even with the State's weight set to only 0.01 the arms would override the base layer's animation completely (resulting in a non-smooth animation), as Layer 1's weight stays 1 even after the State's weight was faded out to 0.

    I guess my question is if there is a way to synchronize the Layer's weight with the State's weight, or do I have to do that manually? Or am I doing something in an uncommon manner and should change it?
     
  24. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
  25. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    348
    But even if I do have something playing on the layer, the animation is not correct when fading out; as I fade out the state, it goes from 1 to 0, but the layer keeps having weight 1, overriding the base layer completely, which looks just wrong. A bit frustrating, because now I have to check manually if there is anything still playing on the layer, ideally every frame.
     
  26. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I'm not sure why you would need to check every frame. When your action ends you either want to play something else or you want to play nothing (i.e. fade out the layer). Any time you're currently telling it to fade out the state, just tell it to fade out the layer instead. If that doesn't cover your use case, can you explain what you're doing in more detail?
     
  27. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    348
    Okay, but I'm not quite sure why I have to do it like this. It wasn't clear to me that layers+states would act like this, even after reading in the manual about layers and states again. Why don't their weights just multiply?
     
  28. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    If having Layer 1 at Weight 1 didn't take over the entire output then you would need to fade out Layer 0 whenever you fade in Layer 1. Animancer could do that under the hood, but that would entirely break masking because if you had to fade out Layer 0 then you wouldn't be able to blend it with an upper body animation on Layer 1.
     
  29. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,681
    Hi @Kybernetik,
    I just got IK working. What is the reason the target needs a collider?
    Thanks!
     
  30. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    The targets in the IK Puppet example have colliders so that the MouseDrag script can target them with raycasts. But the IK system doesn't care where the values come from, you don't even need to have a GameObject for each target, it's entirely up to your script where you want to get the values from.
     
  31. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    Hey everyone, you might be interested to know what the Asset Store is currently having a 50% off sale. Animancer isn't in it, but they're giving away one asset for free every week so there's no reason not to grab it. This week it's a Skeleton Warrior / Knight model.

    Here's my affiliate link to the sale: https://assetstore.unity.com/publisher-sale?aid=1100l8ah5

    That means if you click that link and do buy something, I'll receive a small percentage commission (which doesn't cost you anything extra).

    To get the free asset, just scroll down to the Get Your Gift button, but before you click it you need to copy the coupon code just above it so you can put it in during checkout. This week's code is ROSYAEV.

    The free asset will change to "Magic Swords VFX" from Hovl Studio on the 3rd of August.
     
    Willbkool_FPCS and ratking like this.
  32. TomatoLamp

    TomatoLamp

    Joined:
    Feb 8, 2013
    Posts:
    8
    I had a question involving the 2D Platformer Game Kit, I've slightly repurposed the hitbox related scripts for use in my 3D game but I'm having some issues determining how to proceed.

    I'm referencing AttackTransition animation data as ClipTransitionAsset.UnShared but HitData.InitializeData() modifies the events of the shared transition regardless of how I handle that. Also, the "_HasInitializedEvents" value will remember its setting here (because it's an SO, I presume?) and so I'm unable to rely on that to initialize the HitData properly.

    If you have any insight into how I can tackle this issue, I'd be very grateful. The way you've integrated hitboxes into animation clips is very elegant and I'd love to be able to continue to use and add onto it.
     
  33. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I don't have the code in front of me right now, but if I remember correctly the base UnShared class initializes its events directly from the SerializedEvents of the transition asset. If you change it to use the Events instead, then as long as the asset's Apply method has already been called to convert the hit data into events the UnShared should make a copy of those events which should let it work properly.
     
  34. TomatoLamp

    TomatoLamp

    Joined:
    Feb 8, 2013
    Posts:
    8
    Thanks for your response!

    So now the root of the problem is that "hasInitializedEvents" bool. If I expose it in the inspector and uncheck it manually, it initializes and then works perfectly. But I'm unable to use any mono or SO functions like Awake() to easily reset that value to false and so subsequent runs are unable to make hits. Without the bool, it will continue to re-initialize existing events.

    I can imagine a few ways I could pass information down to the transition but I'd really like to avoid touching as much of your code as possible and it seems that'd involve digging into several classes.

    Do you have any suggestions for a place I could reset that value to false? Anything accessible to the transition that runs once per asset?
     
  35. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    _HasInitializedEvents shouldn't be the source of the problem because the actual hit events get the current character when triggered so it doesn't matter if all characters share the same events, each one's events will find itself.

    So the problem is most likely that AttackTransition.Apply isn't getting called before the UnShared makes its copy of the events so that copy never contains the hit events.

    Making the base AnimancerTransition.Events virtual so that AttackTransition can override it to add the hit events (instead of adding them in Apply) should avoid that issue, but I won't have a chance to test it for a few days.

    I could easily incorporate a change like that into the next version of Animancer if it solves the problem (athough it won't be ready any time soon).
     
  36. TomatoLamp

    TomatoLamp

    Joined:
    Feb 8, 2013
    Posts:
    8
    I was able to get a working fix in, thanks to your explanations. I would love for something "built-in" when you're able to push another update but I totally understand however long it takes. Here's what I've done in the meantime:

    Added ITransition.AugmentEvents(AnimancerEvent.Sequence)
    -> Implemented virtual ClipTransition.AugmentEvents()
    -> Implemented override AttackTransition.AugmentEvents
    ->Runs HitData.InitializeData()​

    Changed AnimancerTransitionAssetBase.UnShared.Apply()
    -> assigns _Events to Events (instead of SerializedEvents, as you said)
    -> runs Asset.GetTransition().AugmentEvents(_Events) immediately after that

    So far so good but if you foresee this causing any issues, that's another story...

    Regardless, thank you again for your time!
     
  37. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    That sounds like it should work, I can't see any immediate issues with doing it that way.
     
    TomatoLamp likes this.
  38. VirtusH

    VirtusH

    Joined:
    Aug 18, 2015
    Posts:
    91
  39. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    I want to make sure I am not going down a rabbit hole with what i want to do, so would appreciate if you could answer this before i invest a lot of time (I have the pro version).

    I have a character setup using your state machines example. I also however need to take advantage of your layers example, so am wondering if the two can be combined, or should I only stick to one example (which in this case would have to be the layers).
     
  40. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    The examples are designed to teach you how to use their respective systems so once you understand them it should be possible to use aspects of both. The Dynamic Layers example demonstrates how you can use a script to manage the layer details (LayeredAnimationManager) while providing a simple interface for the high level gameplay logic (DynamicLayeredCharacterAnimations). I've never worked on a complex multi-layer character, but I'd probably start with making a manager like that for the character's states to interact with instead of letting them directly interact with Animancer.
     
    andreiagmu and nobluff67 like this.
  41. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    thanks, just need basics and stick with the layers example. I find the brain examples confusing from a technical (my skill level) pov.
     
  42. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    172
    Hi! Does anyone here have experience using Animancer with Corgi Engine?
    Any tips/advice regarding this integration?

    Corgi's animation system is Mecanim-based, by default.
    My main intention is to avoid using Mecanim entirely and control my animations through Animancer only. Or at least, use Mecanim as little as possible (see reuno's answer in the Corgi thread I linked below).

    Corgi has its own state machine logic for its characters.
    I'm having difficulty understanding if I still should make "Animancer FSM" scripts to drive my animations (the Animancer FSM would run alongside Corgi FSM), or if I should just extend Corgi's scripts in some way to use Animancer with Corgi.
    What would be the recommended workflow to go with this?


    I asked a similar question in the Corgi forum, about using Corgi with another animation system that isn't Mecanim:

    https://forum.unity.com/threads/rel...ed-damage-system.286289/page-167#post-9256467
     
  43. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    If they already have their own FSM there's likely no point in doing
    Corgi FSM <-> Animancer FSM <-> Animancer
    instead of just
    Corgi FSM <-> Animancer
    . I've never used their system though so I don't have any specific insights.
     
    andreiagmu likes this.
  44. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    Hi there, I noticed that editing/previewing animations in the Animation window works as outlined in https://kybernetik.com.au/animancer/docs/manual/getting/animation-window/ when the gameobjects in question are in a scene, but not when in the prefab editing area. Is this a known issue? It was a little confusing at first because my usual workflow pre-Animancer was to edit them in the prefab view where its isolated from other things and I don't need to remove it from a scene or set up a dedicated scene to animate.
     
  45. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    I'm seeing the same behaviour with Animancer as with an Animator Controller. Selecting a prefab asset doesn't let the animation window work but opening the prefab and selecting it in the hierarchy lets the window work normally for both systems.

    It could be a Unity bug, which version are you using?
     
  46. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    I would have checked back more often if I knew you were so quick to respond :D

    After fiddling around some more, it looks like it works on one of my projects, but not the other - and the difference from what I can see so far is that in the one it doesn't work on, the animator/animancer components are inside a nested prefab. That said the animator with a controller does still work in this scenario for me.

    Here's what it looks like in the hierarchy:
    upload_2023-9-3_23-31-0.png
    The Animator and Animancer components are in the highlighted "Animator" GameObject, while the animation clips are referenced on a script in "Root". Without a Controller, the Animation window works while selecting an instance of this in a scene, but not in the prefab mode. With a Controller, it works in both cases.

    Also, the Unity version I am on is 2021.2.7f1, and yes, I am opening the Root prefab when in prefab mode so that the animation clips are referenced, not the child prefab.
     
    Last edited: Sep 3, 2023
  47. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,485
    It sounds like the issue might be where you're referencing the clips from.

    The Animation Window section and FindRoot page explain how Animancer finds the clips.

    Since your Animator is in the Child prefab, it will treat that as the root object and only search for clips in its children.

    If you want it to go all the way up to the Root, you could make one of the components attached to it implement ICharacterRoot since it takes precedence over the other search criteria.
     
    NotEvenTrying likes this.
  48. NotEvenTrying

    NotEvenTrying

    Joined:
    May 17, 2017
    Posts:
    43
    That worked, thank you!
     
  49. jarrodspurrier

    jarrodspurrier

    Joined:
    Jan 3, 2023
    Posts:
    5
    So it doesn't look like changing the Animator's update mode from Normal to Unscaled Time at runtime has no effect. @Kybernetik, do you have any suggestions around how I might achieve having animations opt into being affected by time scale or not via Animancer? Is there a more elegant way then just modifying the speed of the animations to counter the time scale?
     
  50. jarrodspurrier

    jarrodspurrier

    Joined:
    Jan 3, 2023
    Posts:
    5
    Nvm, I was setting Animator.UpdateMode. When I did AnimancerComponent.UpdateMode it worked.