Say Goodbye to the Animator! NEW Unity Plugin Showcase

แชร์
ฝัง
  • เผยแพร่เมื่อ 20 ต.ค. 2024

ความคิดเห็น • 98

  • @SmallHedgeHQ
    @SmallHedgeHQ  6 หลายเดือนก่อน +12

    Hello! Hope you're enjoying the plugin. One of my subscribers pointed out that calling new() every frame would induce a lot of garbage collection. A work around is to instantiating everything locally beforehand. Such as:
    private readonly AnimationData IDLE = new(Animations.IDLE);
    private readonly AnimationData RUN = new(Animations.RUN);
    private readonly AnimationData ATTACK = new(Animations.ATTACK1, true, new());
    Then pass those in when you need them!

    • @TuberTugger
      @TuberTugger 6 หลายเดือนก่อน +2

      Would be nice to have a tool to bake this automatically. Specifically the animation names as well. You should be able to generate the enum code block from a animation controller pretty easily.

  • @duyinhhoang5472
    @duyinhhoang5472 6 หลายเดือนก่อน +2

    Definitely going to try it!!
    I'm trying to improve my first character and your plugin will definitely come in clutch!
    Thanks a lot!

  • @DaydreamStudios_Official
    @DaydreamStudios_Official 6 หลายเดือนก่อน +1

    Thank you. This video has inspired me to try to make a even more intuitive version of animating through coding!

  • @Br00dl0rd_
    @Br00dl0rd_ 6 หลายเดือนก่อน +1

    Damn, this looks amazing, great work! Will definitely test this out!

  • @davidtourangeau
    @davidtourangeau 6 หลายเดือนก่อน +1

    That's an excellent feedback response to comments!!!

  • @diliupg
    @diliupg 6 หลายเดือนก่อน +1

    Thank you very much for this excellent plugin! People like you are a rare breed. :)

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      :) Just wanting to help out best I can

  • @MalbersAnimations
    @MalbersAnimations 6 หลายเดือนก่อน +1

    Amazing!
    Take a sneak peak into the Playable API when you have the chance :D

  • @jensvide777
    @jensvide777 6 หลายเดือนก่อน +1

    Nice. You even adressed making an exception to allow the hit animation to play regardless of the current state.

  • @ItzVic
    @ItzVic 6 หลายเดือนก่อน +1

    this dude is insane and extremely underrated, I hope this video blows up

  • @mixedtrigenito
    @mixedtrigenito 6 หลายเดือนก่อน

    as a noob that knows little to know coding this was an incredible explanation

  • @WurstOnAir
    @WurstOnAir 6 หลายเดือนก่อน +1

    Nice update on this. Regarding the animator values. I think I would prefer a use of generics instead of having a static list of enum values. Since for bigger projects there will be alot of animation names. So this enum will explode in size. Instead you could use generics with a forced type of System.Enum. This would break your default ctor for the AnimationData but I guess just having an ctor override for an empty new() could easely do the trick and replace the reset enum value just with a bool.
    So the AnimationCoder class top would look something like this:
    public abstract class AnimationCoder : Monobehaviour where TAnimEnum : System.Enum
    The animationData would also need this generic.
    With this change the class can just define which enum it wants to use for setting the animations.

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      Good idea. Having a different list of Enums for each unit. The reason why it was set up like this was so that it’s all in one place and easy to setup.

  • @TheOriginalDarkGlitch
    @TheOriginalDarkGlitch 6 หลายเดือนก่อน

    This should be the default behavior. Good work!

  • @OrbitZeroStudios
    @OrbitZeroStudios 3 หลายเดือนก่อน +5

    So I tried this plugin, and it was a straightforward approach for my project but when dealing with multiple Animation layers, the reset almost always does not work. I found the issue, it was happening because there was only one currentCoroutine for various layers. To fix this issue:
    public abstract void DefaultAnimation(int layer);
    public Animator animator;
    private Animations[] currentAnimation;
    private bool[] layerLocked;
    private ParameterDisplay[] parameters;
    private Coroutine[] currentCoroutine = null;
    /// Sets up the Animator Brain
    public void Initialize()
    {
    AnimatorValues.Initialize();
    Animator animator = GetComponent();
    layerLocked = new bool[animator.layerCount];
    currentAnimation = new Animations[animator.layerCount];
    currentCoroutine = new Coroutine[animator.layerCount];

    • @SmallHedgeHQ
      @SmallHedgeHQ  3 หลายเดือนก่อน +2

      Duude, you are a genius for finding that bug. I really couldn't have made this plugin without this community. Most of the ideas for this plugin came from you all. Really appreciate all the feedback and suggestions. I have committed a new version with these changes on the github page.

    • @OrbitZeroStudios
      @OrbitZeroStudios 3 หลายเดือนก่อน

      @@SmallHedgeHQ[Edit] The above methods works fine there was a mistake in myside of the code that was causing it to through an error.
      Hello there this is very important, Please replace the array of the coroutines with a list, otherwise the plugin will give not work but remain stuck on the default animation.
      private List currentCoroutine = new List();
      /// Sets up the Animator Brain
      public void Initialize()
      {
      AnimatorValues.Initialize();
      //Animator animator = GetComponent();
      layerLocked = new bool[animator.layerCount];
      currentAnimation = new Animations[animator.layerCount];
      // Coroutine[] currentCoroutine = new Coroutine[animator.layerCount];
      currentCoroutine = new List(animator.layerCount);
      // this.animator = animator;
      for (int i = 0; i < animator.layerCount; ++i)
      {
      layerLocked[i] = false;
      currentCoroutine.Add(null);
      int hash = animator.GetCurrentAnimatorStateInfo(i).shortNameHash;
      for (int k = 0; k < AnimatorValues.Animations.Length; ++k)
      {
      if (hash == AnimatorValues.Animations[k])
      {
      currentAnimation[i] = (Animations)Enum.GetValues(typeof(Animations)).GetValue(k);
      k = AnimatorValues.Animations.Length;
      }
      }
      }
      //rest of initialize}
      And later in the Play function
      if (layerLocked[layer] || currentAnimation[layer] == data.animation) return false;
      if (currentCoroutine[layer] != null) { StopCoroutine(currentCoroutine[layer]);}
      layerLocked[layer] = data.lockLayer;
      currentAnimation[layer] = data.animation;
      animator.CrossFade(AnimatorValues.GetHash(currentAnimation[layer]), data.crossfade, layer);
      if (data.nextAnimation != null)
      {

      currentCoroutine.Insert(layer, StartCoroutine(Wait()));
      IEnumerator Wait()
      {
      animator.Update(0);
      float delay = animator.GetNextAnimatorStateInfo(layer).length;
      if (data.crossfade == 0) delay = animator.GetCurrentAnimatorStateInfo(layer).length;
      yield return new WaitForSeconds(delay - data.nextAnimation.crossfade);
      SetLocked(false, layer);
      Play(data.nextAnimation, layer);
      }
      }
      I hope you will see this comment and change the Repository again. There is some problem with using an array. Using array only works when there is no next animation for some reason.

    • @SmallHedgeHQ
      @SmallHedgeHQ  3 หลายเดือนก่อน +1

      @@OrbitZeroStudios hmm that is really bizarre. I’ll look into it tomorrow. Thanks for letting me know

    • @OrbitZeroStudios
      @OrbitZeroStudios 3 หลายเดือนก่อน

      @@SmallHedgeHQ I am such an idiot. It was working fine I had a typo there in the initialize
      Please remember the following text: "Coroutine[]"was added by mistake currentCoroutine = new Coroutine[animator.layerCount];

    • @SmallHedgeHQ
      @SmallHedgeHQ  3 หลายเดือนก่อน

      @@OrbitZeroStudios aha that would make sense!

  • @nah82201
    @nah82201 6 หลายเดือนก่อน +2

    So first off, nice bit of work there. Very clean.
    A couple honest questions:
    1. Is there a performance gain from this?
    2. And either way, outside of ditching visual chaos, what is the benefit from your perspective?

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +5

      Very important and valid questions.
      1. I am not aware how the Unity Animator functions under the hood (other than it is a FSM), so I can't do a direct comparison. In terms of the performance of AnimatorCoder, everything is converted to hashes and the AnimatorCoder.Play() method is O(1) (unless you chain animations together), so it is very quick. The user is in control of how performant it is. Whether they want to do a bunch of checks every frame to play animations, or play animations due to an event. The performance is in the users hands.
      2. First I will point out that is heavily depends on preference. If you are a natural programmer, converting all animations into code can make animations much more intuitive and logical. It is quite frequent in the Unity Animator that every state needs to be connected to every other state, and that takes a lot of time to set up the animator parameters and transition attributes. By default, the states in AnimatorCoder are already connected to every other state. It also allows you to alter the animation transitions at runtime. Since you can easily chain animations together with AnimatorCoder, you can create you own mini FSM and have then cancel whenever you want to. The main advantage of AnimatorCoder is it is quick, efficient, and simple and only requires one line of code to run AnimatorCoder.Play()

  • @alekjatuszyk4976
    @alekjatuszyk4976 3 หลายเดือนก่อน

    i actually used a system similar to this in my AI framework asset, and it is waaaaay easier and nicer than the transitions (asset name: Alek AI Framwork). nice work!

  • @Titanblade17
    @Titanblade17 4 หลายเดือนก่อน +1

    I keep getting the error “Animator.GotoState: State could not be found UnityEngine.Animator:CrossFade (int,single,int)”
    And it sends me to line 138 of the AnimatorCoder script. animator.CrossFade(AnimatorValues.GetHash(currentAnimation[layer]), data.crossfade, layer);
    Any idea what’s happening? I’ve been searching for hours and can’t figure it out.

    • @SmallHedgeHQ
      @SmallHedgeHQ  4 หลายเดือนก่อน +1

      The most likely explanation is the enum value passed in Play() does not exist as a state in the animator. For example, if your animations enum looks like
      Enum Animations
      {
      RUN,
      WALK,
      IDLE
      }
      Then there must be a state that is named RUN, IDLE, or WALK

    • @Titanblade17
      @Titanblade17 4 หลายเดือนก่อน +1

      @@SmallHedgeHQ Ok, I'll try looking at that again! Thanks!

  • @MrBOI-1
    @MrBOI-1 2 หลายเดือนก่อน

    Hey, i am getting errors when i use (On Parameter), the error is : NullReferenceException: Object reference not set to an instance of an object. its saying at line 23 in OnParameter.cs. Thanks

  • @DenisFomin
    @DenisFomin 5 หลายเดือนก่อน

    That's a great approach.
    I'll try to use it in my game, I'm tired of correcting dependencies in the standard animator.
    But for us lazy people, it would be easier if you also put the character control code in the kit, for example ))).

  • @blindsidedgames
    @blindsidedgames 6 หลายเดือนก่อน

    Well then, this is actually super epic. Nice job!

  • @michieldeekens9218
    @michieldeekens9218 4 หลายเดือนก่อน

    Hey man! I am using this instead of the animator now, and I am loving this! But I have a small question regarding blend-trees. If I want to use a Strafe left/right on top of walking/running, how can I achieve this using your code?

    • @SmallHedgeHQ
      @SmallHedgeHQ  4 หลายเดือนก่อน

      Sorry for late reply! Took time off and slowly getting through comments.
      I got asked a lot about blend trees. Unfortunately this is set up to optimise single state transitions, not blending multiple animations together. Best bet is to add more crossfade (transition time) to have walk left, right, forward, back animations and transition between them.

  • @Endless_Existence
    @Endless_Existence 6 หลายเดือนก่อน

    Awsome ! But what about strafing ? Like what we use in 2D blend trees?

  • @ivank8463
    @ivank8463 6 หลายเดือนก่อน

    This looks awesome, but I wonder how would it work with multiple different animators and layers, maybe instead of using one big enum for all the animations you could use scriptable object that stores the names of animations and than just swap that whenever you want to use new animations instead of having them all in one big enum.

  • @albertobertollo1764
    @albertobertollo1764 6 หลายเดือนก่อน

    Maby is more manageable even for multiplayer games. I will give this a try

  • @kfirsde
    @kfirsde 6 หลายเดือนก่อน

    This is amazing!! Thank you so much

  • @akademiacybersowa
    @akademiacybersowa 6 หลายเดือนก่อน

    I just started watching but... Animation.CrossFade is literary what we used before Unity 4.0 and Mechanim system :D

  • @justinrush7463
    @justinrush7463 3 หลายเดือนก่อน

    Hello, I'm aiming to be a new user of this system, but I have one worry. See, when making the system on your own like in the last video, I can use inheritance to give every entity in my game access to their own brain, as I can just make a new class that contains functionally the same things but with the proper data for the entity it will be used with. How do you handle separate brains with this plugin version of it? Because if I'm reading this right, there's only one AnimatorValues script, and all implementation of this plugin will call back to that script, with no way to tell it what values it should be using.

    • @SmallHedgeHQ
      @SmallHedgeHQ  3 หลายเดือนก่อน

      I suppose this is where there is a balance for convenience and optimisation. This method prioritised convenience (having one global AnimatorValues) and ease of use rather than each animator having their own set of values. A design decision that I thought was a good trade off.

  • @nightonmars
    @nightonmars หลายเดือนก่อน

    Not tried it yet but wondering if using Cysharp's Unitask could be a way to reduce garbage?

    • @SmallHedgeHQ
      @SmallHedgeHQ  21 วันที่ผ่านมา

      The difference does seem pretty minimal but might work slightly faster if you have a mega animation chain :D. Otherwise not sure how much difference it would make.

  • @512Squared
    @512Squared 6 หลายเดือนก่อน

    😊 nice work. Rather than call New() for your animation reset, i would change your input to a second boolean isReset, and then an optional overload after that for the chained animation. Then pass the job of creating that reset to your animator class based on the boolean. But using the overload you get the option to specify or not. It would be easier for newbies, me thinks

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      You might be onto something, can you clarify what you mean with code examples?

  • @alisoundz
    @alisoundz 6 หลายเดือนก่อน

    this is so amazing, we need a discord!!

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      It might happen!

  • @jonas0608
    @jonas0608 หลายเดือนก่อน

    Hi, I'm running into a problem where when I Jump i go through the FALLING Parameter into my IN_AIR Animation and then with the GROUNDED Parameter into the JUMP_LAND Animation.
    When I'm in Idle Animation (I've got 5 idle Animations that i loop through) and press JumpButton, the JUMP_START Animation plays but I think it's affected by the Idle Animation before. I would guess it's because of Crossfade. But then again, when I'm in WALKING or RUNNING Animation this Error doesn't occur even though I have crossfade on these as well.
    Also the JUMP_LAND Animation does often not play when I'm not moving and it goes straight back to IDLE.
    If anyone seem to recognize this or may know where I made a mistake, please answer.
    Help is greatly appreceated!
    3D Game
    I used another Script for my Character Controller
    My Code:
    using System.Collections;
    using UnityEngine;
    using SHG.AnimatorCoder;
    public class NewAnimationSystem : AnimatorCoder
    {
    public static NewAnimationSystem instance;
    private BasicPlayerMovement basicPlayerMovement;
    private Vector2 movement;
    private bool playIdle;
    private bool isCautious;
    [Tooltip("The time between Idle Animation switch when standing")]
    public float switchIdleTime = 7f;
    private int randomIdleAnimation = 0;
    private int randomCautiousIdleAnimation = 0;
    Animator anim;
    void Awake(){
    instance = this;
    }
    void Start()
    {
    Initialize();
    basicPlayerMovement = GetComponent();
    anim = GetComponent();
    StartCoroutine(ChangeIdle());
    IEnumerator ChangeIdle(){
    while (true){
    yield return new WaitForSeconds(switchIdleTime);
    randomIdleAnimation = Random.Range(0, 6);
    randomCautiousIdleAnimation = Random.Range(0, 2);
    }
    }
    }
    void Update()
    {
    movement.x = Input.GetAxisRaw("Horizontal");
    movement.y = Input.GetAxisRaw("Vertical");
    DefaultAnimation(0);
    StandMoveAnim();
    CrouchAnim();
    JumpAnim();
    if(playIdle) LoopThroughIdleAnimations();
    }
    void FixedUpdate(){
    SetBool(Parameters.GROUNDED, basicPlayerMovement.grounded);
    SetBool(Parameters.FALLING, !GetBool(Parameters.GROUNDED) && basicPlayerMovement.rb.velocity.y < 0);
    SetBool(Parameters.MOVING, movement != Vector2.zero);
    SetBool(Parameters.WALKING, basicPlayerMovement.currentMoveSpeed = basicPlayerMovement.crouchSpeed + 0.1f);
    SetBool(Parameters.SPRINTING, basicPlayerMovement.currentMoveSpeed > basicPlayerMovement.sprintSpeed - 1.5f);
    }
    void StandMoveAnim(){
    if(Input.GetKey(KeyCode.LeftControl)) return;
    if(GetBool(Parameters.GROUNDED) && GetBool(Parameters.SPRINTING)){
    PlayNormalAnimationWithCrossfade(Animations.RUNNING);
    }
    else if(GetBool(Parameters.GROUNDED) && GetBool(Parameters.WALKING)){
    PlayNormalAnimationWithCrossfade(Animations.WALKING);
    }
    else if (GetBool(Parameters.FALLING)){
    PlayNormalAnimationWithCrossfade(Animations.IN_AIR);
    }
    }
    void CrouchAnim(){
    if(!GetBool(Parameters.MOVING) && Input.GetKeyDown(KeyCode.LeftControl)){
    SetLocked(false, 0);
    Play(new(Animations.STAND_TO_CROUCH, true, null, 0.1f));
    }
    if(Input.GetKey(KeyCode.LeftControl)){
    playIdle = false;
    if(GetBool(Parameters.MOVING)){
    PlayNormalAnimationWithCrossfade(Animations.CROUCH_WALK, 0.15f);
    }
    else{
    PlayNormalAnimationWithCrossfade(Animations.CROUCH_IDLE_01, 0.135f);
    }
    }
    if(!GetBool(Parameters.MOVING) && Input.GetKeyUp(KeyCode.LeftControl)){
    SetLocked(false, 0);
    Play(new(Animations.CROUCH_TO_STAND, true, new(), 0.1f));
    }
    }
    void JumpAnim(){
    if(GetBool(Parameters.GROUNDED) && Input.GetKeyDown(KeyCode.Space) && !basicPlayerMovement.readyToJump){
    Debug.Log("Current Transition: " + anim.GetAnimatorTransitionInfo(0));
    SetLocked(false, 0);
    Play(new(Animations.JUMP_START, true, null, 0.1f));
    }
    }

    void LoopThroughIdleAnimations(){

    if(!isCautious){
    switch (randomIdleAnimation){
    case 0:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_IDLE_01);
    break;
    case 1:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_IDLE_02);
    break;
    case 2:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_IDLE_03);
    break;
    case 3:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_IDLE_04);
    break;
    case 4:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_IDLE_05);
    break;
    }
    }
    else{
    switch (randomCautiousIdleAnimation){
    case 0:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_CAUTIOUS_IDLE_01);
    break;
    case 1:
    PlayNormalAnimationWithCrossfade(Animations.STANDING_CAUTIOUS_IDLE_02);
    break;
    }
    }
    }
    //Just to make it shorter
    private void PlayNormalAnimationWithCrossfade(Animations _animation, float _crossfade = 0.2f){
    Play(new(_animation, false, null, _crossfade));
    }
    public override void DefaultAnimation(int layer)
    {
    if(Input.GetKey(KeyCode.LeftControl)) return;
    if(!GetBool(Parameters.MOVING) && GetBool(Parameters.GROUNDED) && !GetBool(Parameters.FALLING))
    playIdle = true;
    else
    playIdle = false;
    }
    }
    My Parameters in the Animator Editor are:
    On JUMP_START: Falling Parameter -> Play IN_AIR Animation
    On IN_AIR: Grounded Parameter -> Play JUMP_LAND Animation -> Next Play RESET
    On JUMP_LAND: Walking Parameter -> WALKING Animation ; Running Parameter -> RUNNING Animation ;

  • @mohamedhamed3572
    @mohamedhamed3572 3 หลายเดือนก่อน

    Amazing!

  • @junyuhan-to6kw
    @junyuhan-to6kw 4 หลายเดือนก่อน

    What if I want to randomly play multiple animations of each type with this plugin

    • @SmallHedgeHQ
      @SmallHedgeHQ  4 หลายเดือนก่อน

      Each layer holds one singular current animation at a time and is tracked through an enum. So to pick a random animation, you could do Animations[Random.Range(0, Enum.GetNames(TypeOf(Animations)).length] to get a random animation. Or make a list of Enum values to randomly choose from. Each Enum value is given an integer, which allows you to look up them through an array.

  • @yassin_GameOver1
    @yassin_GameOver1 6 หลายเดือนก่อน

    Very useful and very good
    Thank you so much 🎉

  • @luluca5
    @luluca5 6 หลายเดือนก่อน

    So I suppose this plugin can only work with the situation that there’s no transition between animations and the animation must fully played before playing the next animation?

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      AnimatorCoder does allow transitions and overridable animations.
      Transitions: In the Play() method, you can set the crossfade of the animations so transition them over a number of seconds.
      Fully played: When you call Play(), it will automatically override the current playing animation. Unless you set LayerLocked = true, then no other new animations can play while the animator is locked.
      So you can play animations fully if it is an important animation. Or set it to be overridable by other animations.

  • @iqra8823
    @iqra8823 6 หลายเดือนก่อน +1

    Bro your the Goat

  • @muhammedemen5122
    @muhammedemen5122 6 หลายเดือนก่อน

    Great job!

  • @TuberTugger
    @TuberTugger 6 หลายเดือนก่อน

    Does this handle animation blend trees?
    Seems great for platformers but omnidirectional animations, like top down or 3d animations absolutely require blends.

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      Unfortunately it does not support blend trees and I agree. This plugin excels when the only form of blending are simple cross fade transitions. Which typically occurs in 2d projects and certain 3d situations. I did make a video using this plugin in 3d with multiple animator layers. One animator layer was the Upper Body and the other Lower Body. Then the animation logic in code was done in a way to try simulate blend trees by playing forward, back, left, and right walk animations when conditions were met. So like any plugin, it has great strengths and also some limitations, it would be just knowing what situations to use it and when not to use it.
      th-cam.com/video/Db88Bo8sZpA/w-d-xo.html

  • @TREXYT
    @TREXYT 6 หลายเดือนก่อน

    Is it more performant than mesh animator ? Which convert our animations to shader

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      AnimatorCoder.Play() is O(1) by default, so it depends how you use it in your scripts.
      I had a quick look at the Mesh Animator asset. If all the animations are baked, could you combine AnimatorCoder and Mesh Animator together by changing what AnimatorCoder.Play() does?

    • @TREXYT
      @TREXYT 6 หลายเดือนก่อน

      @@SmallHedgeHQ how can i combine while 1 is an animator and the other is a sprite sheet of animations ?

  • @typhereus
    @typhereus หลายเดือนก่อน

    Does this work with bone animations? (2D Skinning)

    • @SmallHedgeHQ
      @SmallHedgeHQ  21 วันที่ผ่านมา +1

      Yes should work, if your animation is an animation state in the animator window

  • @스폰지밥-v9r
    @스폰지밥-v9r 4 หลายเดือนก่อน

    You are the best 😍😍😍😍 Thanks!!

  • @andyjoensen3949
    @andyjoensen3949 6 หลายเดือนก่อน

    Very Nice!

  • @teammdyss
    @teammdyss 6 หลายเดือนก่อน

    Am I missing something or do I have to add ALL animations I have to one Enum? What if I have 10 different entities each with different animation?

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +2

      I deliberately set it up that way! In the demo scene, there was the samurai and the wizard and they shared their state names. Using AnimatorCoder.Play(Animations.ATTACK1) on the samurai triggers the swing animations, while it triggered the firebolt animation on the wizard.
      Try to overlap them as much as you can. Most units have a RUN animation, WALK animation, multiple IDLE animations, multiple ATTACK animations, JUMPSTART JUMPAIR JUMPEND animations etc. It was done this way so you only need to set up AnimatorCoder once and not for every single unit you create.

  • @badumtsy
    @badumtsy 6 หลายเดือนก่อน

    Hi, do you have some kind of comparison post about this vs animator vs playables?

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      Hello! Sure thing. Playables are like nodes connected in the PlayableGraph, It is a FSM.
      Playables Workflow:
      Have a PlayableGraph and add nodes (new animations) when you need them. Link the nodes together and now you have a FSM. It runs in the background and it will play the desired animations dependant on how it's set.
      Pros: Replicate the FSM nature of the animator into code
      Cons: Takes a while to setup
      Animator Workflow:
      Link animation states together using transition lines which play depending on animator parameters
      Pros: Highly visual, quick to setup, lots of features (blend trees, transition options, behavior states etc)
      Cons: Becomes more complicated the bigger it gets. Gets hard to keep track of everything
      AnimatorCoder Workflow:
      Create a list of conditions that need to be met to play an animation and use AnimatorCoder.Play() to play them. It will execute a bunch of O(1) checks to validate the request and then the animation is played.
      Pros: Quick to setup and requires only one universal setup, easy to use, minimal code, highly intuitive
      Cons: Doesn't provide functionality for blend trees
      We worked on AnimatorCoder because it is an animation system that works no (or very little) setup and works straight out of the box. It's the most intuitive animation scripting design I know.

  •  6 หลายเดือนก่อน

    it was good until the onparameter script, which is the same as the animator transitions just with less options... if you make it that we can add these data to the animationdata, then it will be much better solution

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      The parameter check only needs to occur when you are in the specific animator state. This was eliminating the need to check parameters each frame when you don’t need to.

  • @steluste
    @steluste 6 หลายเดือนก่อน

    Nice work. Nice video. But I usually play animations using Animator.Play or Animator.CrossFade(for blending) and I don't see any difference between using your asset and my method. Maybe I'm wrong. If I am then let me know.

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      Someone else had a similar question! So I'm just going to copy paste the response. I suppose you can treat AnimatorCoder as Animator.Crossfade+. Here's a list of additional features it gives to Animator.Crossfade():
      1. Hold the CurrentAnimation: So you don't use Animator.Crossfade() on an already playing animation
      2. Ability to lock/unlock layers: Some animations need to play all the way through without interuption
      3. Play consequent animations: When an animation finishes, choose what animation to play next
      4. Select animations through enums: Passing through an enum to play an animation is quick and easy
      In a nutshell, it adds a bunch additional checks to Animator.Crossfade() to ensure the requested animation is allowed to play.

    • @steluste
      @steluste 6 หลายเดือนก่อน

      @@SmallHedgeHQ oh I get it now thanks. It's more like you upgraded state machine side of things. Cool. I'll have a look at it.

  • @TheGamingWiccan
    @TheGamingWiccan 6 หลายเดือนก่อน

    how would i use this to implement swimming diving paragliding and free climbing

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +1

      Sounds like you’re going to use multiple animation layers and ik positions. Start small and pick one of them to start off with. If you would like an example of multi-layered animation workflow in 3d, I would check out the previous video on animations th-cam.com/video/Db88Bo8sZpA/w-d-xo.htmlsi=V5b2KJ-YV4BWuAYc

  • @lil_toucan_
    @lil_toucan_ 6 หลายเดือนก่อน

    i love the coding community

  • @Whatisitlol
    @Whatisitlol 6 หลายเดือนก่อน

    Can i use it if i am using visual scripting in unity??

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน

      I haven't give visual scripting a go so not too sure! If you are able to play methods from specfic scripts attacted to gameobjects, you should be able to!

    • @Whatisitlol
      @Whatisitlol 6 หลายเดือนก่อน

      ​@@SmallHedgeHQi am gonna try it today

  • @lawrence9713
    @lawrence9713 6 หลายเดือนก่อน +1

    As a non programmer: What?

  • @juice1884
    @juice1884 6 หลายเดือนก่อน +1

    This is not really scalable to an actual game lol, the Animations and Parameters enums are going to grow to unwieldy sizes

    • @SmallHedgeHQ
      @SmallHedgeHQ  6 หลายเดือนก่อน +2

      I suppose so is the Unity animator window xD

    • @juice1884
      @juice1884 6 หลายเดือนก่อน +1

      ​@@SmallHedgeHQ Well, at least the unity Animator window doesn't list all parameters of all animation controllers in a single window
      You can introduce generic type parameters in your AnimationCoder class to force the inheritor to pass in their own enum classes for both the Animations and Parameters

    • @EudaderurScheiss
      @EudaderurScheiss 6 หลายเดือนก่อน

      yes but you can search them. i use a similar approach where i hash the animations before hand. if you play something in code you can always look up where it is triggered and from what.

  • @LuKaion77
    @LuKaion77 6 หลายเดือนก่อน

    지리네ㅎㄷㄷ

  • @rusydirosli9423
    @rusydirosli9423 6 หลายเดือนก่อน

    Reset is pronounced as "Reset" not "Receipt". Bool is pronounced as "Bool" not "Ball". Check is also pronounced as "Check" not "Chick". BTW great asset overall, marvellous!!!

    • @Titanblade17
      @Titanblade17 4 หลายเดือนก่อน +2

      Bro’s really making fun of his accent, how petty can you get

  • @halivudestevez2
    @halivudestevez2 6 หลายเดือนก่อน +1

    I cannot follow this. I'm good with the animatior so far, just learn to use blendtrees, and layers.

  • @RoxGame
    @RoxGame 6 หลายเดือนก่อน

    good solution but will not work with network animator (mirror , netcode , fishnet)