Search Unity

choose random animation

Discussion in 'Animation' started by tree_arb, Jan 27, 2021.

  1. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    What is the cleanest way in the animator to have multiple random animations for a scenario

    example:

    Code (CSharp):
    1. if(Player.isShot){
    2.  
    3. m_Animator.SetBool("isShotRandomAnimations", m_isShot);
    4. }
    5.  
    I would like to just pass the animator just one bool, and then have a bucket of random isShot animations to play. I would like to have one bool to go to a substate of random animations, and that same bool all returns to "dead" or whatever.

    right now im really just treating everything completely separate and choosing the random state before anything. Something like this:

    Code (CSharp):
    1. bool isShot1;
    2. bool isShot2;
    3. bool isShot3;
    4. bool isShot4;
    I'm messing with the state machines but seem to be confused
     
  2. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    I use integers as parameters, for a very simple reason: an integer can contain any number, but it must be a whole number. A random integer between two values is also easy to generate from code. So I'd make a system that generates a random integer when needed, and feeds this integer to the Animator using the SetInteger method.

    I didn't get what you mean by this exacly. If the intent is to make the animated character "die" after each animation (without caring which one played), you can simply transition every "is shot" animation into the "dying" animation without parameters, but with some Exit Time. In this case it might be good to make your code consider the character "dead" the moment the "is shot" animation starts.
     
  3. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    thanks, and sorry for delay in reply.

    So I guess I really mean to ask how to organize it better in animator.
    I generate a number in script, and then call animation 1,2,3 or 4. which are all the just variations of falling. (top 4 animations in pic)

    here is a pic how i have these 4 falling animations.
    They all come from and go to the same destinations.

    What I would like to do just for organization of this main animator view is put these 4 animations in a "folder" here. I tried messing w the state machines but it always wants to default to one of the animations within.

    So I can send in a random int, but i guess im not sure what to do with that from there. to send the animator to my multiple set of random choices "folder" and choose an animation.

    admittedly I got lazy and could have googled a little harder. I just kinda set it up sloppy like this, which is working "fine" and kept going.

     
  4. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    No worries. I'm glad you got it working. You are right that this quickly becomes a (visual) mess despite the logic being sound. I do not kow of a way to organise nodes in the Animator. It would surely benefit from such an option.

    I use a similar setup with my "speed" variable, where the character can be idle (0), walking (1) or running (2). The only difference is that these states feel more important then 4 random jump animatons. I too get that "is this function worth all this hassle" and strive for simplicity. I have come to accept animating a human is everything but simple, and this organised mess is simply the cost of making things feel more alive and varied.

    That being said, you could look into animation layers as well. I use them with an avatar mask, so I can animate just the upper body (my character can casts spells when walking or running). But you can also not apply such a mask, and then move these animations to that layer. I'm not sure what you should have running in your main layer, but I think you can just add an empty state for anything that is not a jump and then transition to 4 jumping animations using the same parameter setup.

    I might try this myself as I'd like to switch up my double jumping animation. If I get around to that I'll post my findings here.
     
  5. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    By the way, have you looked into Animation Layers and Blend Trees yet? While they would add some complexity to your Animator, you could (for instance) use a single node for jumping in the base layer, and organize 4 variations in another layer that use an Int to select which animation is used to override the original.
     
  6. Sim-john

    Sim-john

    Joined:
    Feb 4, 2021
    Posts:
    2
    Create a state in way so that randomly pick that.
     
  7. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    I've been messing with three different idle animations that play randomly after certain conditions are met. I feed my Animator two values that the base layer doesn't use:

    idle is a bool; true when the character does anything and false when it is completely still.
    idlePose is an integer; determined at a fixed interval for now with Random.Range().

    I've put three variations of a (non looping) idle animation on a layer named idle Layer. The default state has no animation at all. It does have a transition towards the three seperate states with two conditions (and AND scenario): idle must be true and idlePose must be equal to a certain value (1,2, and 3). Each of those conditions in turn, has two transitions back to the default state (and OR scenario):
    • One that has the condition idle = false. Whenever we move we want to cancel the animation immediately.
    • One that had the condition idlePose = 0. There are two ways for this parameter to become zero.
    idlePose becomes zero when:
    1. Any of the animations reached the OnIdleLayerEnd Animation Event I added a second or so before the end of the animation. You can do this either in the import window of the animation, or copy-paste in all the keyframes in a new one. I prefer this as it allows me to work on the actual keyframes and delete the root transform node.
    2. Update() checks whether or not isIdle is true or false. When false it sets the idlePose value back to zero. This is to ensure that when isIdle becomes true again, it doesn't immediately run the animation that was selected previously. It waits for the interval to select a new random value.
    Now all I need to do is improve how the interval actually works, but it's a neat example of how you can organize animations into "folders" (layers that is) if you're willing to do some extra coding and animation setup stuff.