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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

What is going on with this random animation code?

Discussion in 'Scripting' started by Lethn, Jun 6, 2018.

  1. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    This is very random, but I stumbled across what looked like code for a random playlist for animations and it looks much simpler than a method I was looking at before which involved ridiculously elaborate sub-state machines and so on. I don't know whether it's slightly out of date or what but it's using animation.Play so would somebody mind explaining what's going on here? The array is obvious which is mainly what I want to use but I just want to make sure I understand how to correctly put this into 2018 code.

    https://answers.unity.com/questions/898841/random-animation-from-array.html

    Code (CSharp):
    1.           if (!animation.IsPlaying ("Axe_Hit") && !animation.IsPlaying("Axe_Unsheet"))
    2.           {
    3.               if(Input.GetMouseButtonUp(0))
    4.               {
    5.                   //Random animations from the array playing here
    6.                   animation.clip = animationer[Random.Range(0, animationer.Length)];
    7.                   animation.Play();
    8.                   Invoke("attack", 0.5f);
    9.               }
    10.           }
     
  2. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
  3. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    It popped up with 15 errors when I imported it to my project.
     
  4. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    Did you read them?
     
  5. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Okay, here are all of them.

    For the record, I'm running on Unity 2018.1.1f
     
  6. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
  7. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    After having a poke around on that blog it looks like that component is out of date and only compatible with Unity 2017, looks like learning how to play animation clips at random through an array is probably still my best option.
     
  8. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Back to arrays, I managed to get rid of the errors on one line but I have no idea how to progress from here.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MoonPlayRandomAnimation : MonoBehaviour {
    6.  
    7.     public AnimationClip [] moonAnimationsArray;
    8.  
    9.     void Update ()
    10.  
    11.     {
    12.     //    GetComponent<Animation>().clip = moonAnimationsArray [Random.Range ( 0, moonAnimationsArray.Length ) ];
    13.     //    GetComponent<Animation>().Play;
    14.  
    15.         gameObject.GetComponent<Animation>().clip = moonAnimationsArray [ Random.Range ( 0, moonAnimationsArray.Length ) ];
    16.         gameObject.GetComponent<Animation>().Play;
    17.  
    18.     }
    19.  
    20. }
    I would have thought you simply use gameObject.GetComponent<Animation>().Play; however when I do this it throws up an error. This makes sense right? I have a bit of a better understanding of the code I'm looking at now and it's creating an array and grabbing the animation component and cycling through the animations using Random.Range which is exactly what I want.

    I think this code is just a bit out of date and yes, looks like I'm right, no idea why this isn't working.

    https://forum.unity.com/threads/animation-play-not-working-unity-not-recognising-it.399416/

    Edit:

    Huh, well as it turns out I've at least gotten rid of the errors.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MoonPlayRandomAnimation : MonoBehaviour {
    6.  
    7.     public AnimationClip [] moonAnimationsArray;
    8.  
    9.     void Update ()
    10.  
    11.     {
    12.        
    13.         GetComponent<Animation>().GetComponent<Animation>().clip = moonAnimationsArray [ Random.Range ( 0, moonAnimationsArray.Length ) ];
    14.         GetComponent<Animation>().GetComponent<Animation>().Play();
    15.  
    16.     }
    17.  
    18. }
    19.  
    It seems to be working but now I've got to look at why there aren't any animations playing, might be to do with the animator.
     
    Last edited: Jun 6, 2018
  9. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Okay, sorry if I seem a bit spammy today but I can see I'm really close to fixing this.

    This is the correct code, but I have no idea how to use animation.Play(); in this context what I mean by that is after double checking how the legacy animator works it requires a string for an animation to play. However in the code provided as you can see there isn't any, while the array itself is cycling through animations on the inspector the animations themselves aren't playing and I think that's because the play function isn't pointed to the array.

    Does that make sense? Would appreciate some help with this bit.
     
  10. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    If it's okay with the mods I'm bumping this because it got pretty far down the pages and I'd like a response.
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,186
    Use SimpleAnimation. The errors you're getting are all about the unit testing library NUnit not being found, but you're not going to be running those unit tests, so you might as well just delete the entire testing folder.

    The Animation component is deprecated and will probably fail in a million ways, so using it is just going to cause pain. SimpleAnimation is a rebuild of the Animation component on top of Playables, so it's a much safer bet.
     
  12. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Thanks! That seems to have done the trick, no more errors, one problem though, I'm a total noob with this, never seen it before in my life, how do I access the editor provided with the asset?

    Edit: wait, never mind, everything's clicking now, didn't realise I had to download the editor seperately.

    https://github.com/Unity-Technologies/graph-visualizer

    Yeahhh, okay, time to play around and look at how this thing works :p
     
    Last edited: Jun 7, 2018
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,186
    You don't need the graph visualizer to use SimpleAnimation. You just slot in animations and ask them to play. The graph visualizer is a tool for looking under the hood to see what's going on internally.
     
  14. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Ah heck, I've totally misunderstood what this all is then, would you mind giving me an idiot proof mini-tutorial for it? I'll be able to look back on this later for reference and it will help out other noobs too because I had never even heard of this tool before.
     
  15. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    It's all well and good telling me to use the SimpleAnimation asset but if I don't have an explanation of how to use it I can't. If I don't get a response I'll be looking into using arrays and so on again since that's the only way I can see me getting everything done because there's only that obscure blog available that's got information on it and I haven't been able to find tutorials elsewhere.
     
  16. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    side question to this topic, but; the older animation system is "legacy" rather than "deprecated"... no?

    deprecated being "don't use this going forward we're going to be taking it out at some point, potentially without any notice", rather than legacy which is just "we want to use this name for the new thing that'd more comprehensive and we have to differentiate the two somehow... ". Or did I miss something from the devs on this?
     
  17. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Ugh, I don't know what to tell you, the whole animation code has been driving me nuts and all I want to do is play my animations randomly every few seconds lol.
     
  18. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Sigh, back to square one, after doing a lot of digging yesterday I've realised that although I had absolutely the right idea with the code I found it looks like sprites aren't even supported by legacy animations :(

    At least I've ruled out that option now, so it's either this weird SimpleAnimation script or going back to the previous method I had found where you use a sub-state machine to cycle through the animations that way. My only problem with this method is it was going far too quickly and the animations would overlap each other which I think may be due to the exit time and so on.

    It's frustrating because I can see there's even a 'list' there on the SimpleAnimation component and I can see that it's all connected up to the animator, I genuinely can't find tutorials on it. I suspect partly because of how generically named the damn thing is.
     
  19. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Okay guys, I actually ended up fixing the problem by experimenting a lot and going back to using sub-state machines, it looks like that's why way you need to go if you don't know how to use the ScriptAnimation component. I'm going to do a write up for people because it's that annoying and complicated, very glad I finally fixed this but holy crap, why Unity?

    I need some ice cream after all of this :(
     
  20. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Okay, about ready to post an explanation now, so there were several things that went on with my investigating when it came to just getting random animations working. The first was me checking out legacy animations because that looked the most promising with the code, I decided that I'd try out using an array to play my animations, this did work however low and behold because I was using sprite based animations they wouldn't even play correctly.

    Back to square one, this is why I made this thread, I simply hadn't realised that it wasn't possibly to use legacy animations for sprite based work. I then eventually after all this posting went back to this method I had looked up awhile ago but simply hadn't understood because I didn't know enough about transitions generally and the way states worked.

    Now though I have absolutely everything setup perfectly and since it was so damn difficult I'm doing this write up to help newbies like me with it. First up check this guys' tutorial even though he misses out a lot of stuff because he was only doing it one way it's very helpful to watch through it all, it does go on a bit but it will help you with the basics of the technique.



    To save time for everybody, here's the code that I ended up with, now, one very important thing to note is that for this to work sensibly you have to have the same amount of integers as animations you want to play randomly. Otherwise what will happen is the code will flip through integers that aren't there making the animations look strange.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MoonPlayRandomAnimation : StateMachineBehaviour {
    6.  
    7.     public string m_ParameterName = "MoonID";
    8.     public int[] m_StateIDArray = { 0, 1, 2 };
    9.  
    10.  
    11.  
    12.     // OnStateMachineEnter is called when entering a statemachine via its Entry Node
    13.     override public void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
    14.  
    15.     {
    16.         if ( m_StateIDArray.Length <= 0 )
    17.  
    18.         {
    19.             animator.SetInteger ( m_ParameterName, 0 );
    20.         }
    21.  
    22.         else
    23.  
    24.         {
    25.             int index = Random.Range ( 0, m_StateIDArray.Length );
    26.  
    27.             animator.SetInteger ( m_ParameterName, m_StateIDArray [index] );
    28.         }
    29.     }
    30. }
    31.  
    He explains this in the video, but what this code does is it checks for transitions named as the parameter assigned and then randomly cycles through them using random.range the integers are assigned to these transitions and therefore the animations and that's how this code works. Go through this first so you know what I'm on about and get everything set up.

    What he doesn't explain is that there are various tweaks you need to do to make sure the timing of the animations is correct and you may have your own way of doing things. Now the most obvious problem I immediately ran into was that animations were overlapping each other and playing instantly, all very weird, there were three things I had to do to solve this. One was to simply change the transition duration and exit time in order for it to have an effect on your animations you need to go into the sub state machine you've setup for the code and click on the white this made the animations last longer so they wouldn't skip about.

    This still wasn't enough though, as I was still having issues with timing and my default animations were playing over each other rather than playing randomly and it made everything look weird. What I did was I made the default orange state machine blank, I removed the animation entirely and that actually even helped with the timing because there was a gap between the animations when they changed it would then switch to the sub state machine smoothly and pick an animation at random.

    Again though, another problem, sometimes though the animation wouldn't end correctly and just loop itself, this one proved easiest to fix I simply went into the animation clips one by one and disable loop time. This meant the animation actually ended now and even had a nice little delay due to the blank state machine I had made as the default state machine rather than two of the same animation.

    That's just about the end of my writeup, I really hope this helps newbies who were struggling with what should be something simple to do, if anyone has any corrections and so on to make feel free but I think I got everything. These few days have been absolute hell dealing with this problem but I'm glad I got it sorted.

    Why couldn't Unity just code in some kind of simple randomiser state? I had an extra think about this and if you wanted to use the code here for some kind of randomised attack animations perhaps then you should be able to use a public animator object and 'SetInteger' to cycle between the animations whenever you do a mouse click. Or I guess you could even just grab the integers and set them directly through the script.
     
    Last edited: Jun 9, 2018