Escaping Unity Animator HELL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This post appears to be a direct link to a video.

As a reminder, please note that posting footage of a game in a standalone thread to request feedback or show off your work is against the rules of /r/gamedev. That content would be more appropriate as a comment in the next Screenshot Saturday (or a more fitting weekly thread), where you'll have the opportunity to share 2-way feedback with others.

/r/gamedev puts an emphasis on knowledge sharing. If you want to make a standalone post about your game, make sure it's informative and geared specifically towards other developers.

Please check out the following resources for more information:

Weekly Threads 101: Making Good Use of /r/gamedev

Posting about your projects on /r/gamedev (Guide)

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

👍︎︎ 1 👤︎︎ u/AutoModerator 📅︎︎ Sep 18 2020 🗫︎ replies

What's wrong with that

👍︎︎ 1 👤︎︎ u/[deleted] 📅︎︎ Sep 20 2020 🗫︎ replies
Captions
so if you are working on a 2d game with frame based animations and your animator tab looks like this this or this well you are very likely in the chaotic realm of animator hell so please follow me back into the light back to a place of order so in my past devlogs and tutorials i've often showed a glimpses of my animator tab we've nicely laid out animation nodes with no transition links or spider web-like structure a lot of people reached out to me for information as to how i managed to do this so let me explain so this here is the unity animator tab i'm sure you know it the nodes represent the different animations attached to a particular game object almost every tutorial i've seen for making simple frame based animation changes with even pixel art for instance is pushing beginners into this complex network of nodes linked together through these animation transitions each transition line when selected will have on a number of different settings many of which are not even applicable to frame based animation things like animation blending this network is then tied to a list of animator specific parameters where instead of just specifying what animation should be played you are required to set a bunch of animator specific conditions things like is grounded or player speed or things like that this whole system is sometimes referred to as the unity mechanism well you see in a simple tutorial when you only have like three animation states like a jump run or an attack then sure this approach might be manageable laying things out in its pretty little triangle structure that you often see but try to do this with more than 10 animations or in my case 48. if you have tried this approach then you might have played the fun little game of trying to find an orderly and aesthetically pleasing structure to your layout it's a lot of fun not really and throughout the internet there is no shortage of developers voicing their anguish as they fight against this system i mean look at this poor soul here and the same goes for things like blender trees they're not the optimal solution for frame based animation i mean the name itself is very telling of that blend trees which is inherently designed for blending skeletal animations between different states but if you are working on 2d frame based animations this topological animator approach very quickly leads to animations twitching flickering overriding each other or straight up not playing as situations can easily emerge where multiple animations fight for priority and essentially just get locked for a code oriented programmer like myself it's just clumsy to work with i myself lost weeks of time wrestling with this system until i was eventually like what the hell am i doing here and realized this is not the right approach for me or my game you see when making frame based 2d games you don't need any of this beginners often don't realize you can just tell the animator directly what animation it should play then manage the animation states with custom code much more efficiently and easily and if something doesn't work it's a lot easier to see what went wrong you need a reference to the animator component but this time instead of using animator conventions like setfloat setball into manager animations we are going to use the animator dot play functionality where we can pass in the name of our animation as a string you see when you use that first approach with that set bull set float you are offloading the logic to another system a black box essentially and all this is often getting wrapped up into yet another layer of custom conditional code anyway creating layers upon layers of conditional wrapping like a stinky onion it's much simpler to manage all the conditional logic in one place with a custom code approach so how do we use this approach to manage multiple animations we simply need a reference to the animator a string called current state and a change animation state function which will take a single argument of the new state of type string so within this new function we can start by telling the animator to play the new state we will also write what is known as a guard if this will stop the same animation trying to play that is already playing essentially then finally we will reassign the current animation state to the new state this change animation state function is at the core of how we are going to be managing our animation states alright so let's now take a look at a practical real world example of this using an actual player controller so i've got this little sample scene here i've mocked up i'm just going to run it to show you guys what's going on so we've got mega man he's moving around he's jumping but he's not animating and if we go up into the animator window for the player you can see here i've got a series of animations nicely laid out to represent the different animations that mega man might have got idle run jump player attack and play air attack and i'm going to give this project for you guys down below so you can grab it you can follow along with me and you can work out how we integrate these animations so this isn't one of those tutorials where you have to follow along with the code writing it yourself you can kind of sit back and watch it as more of a lecture format but if you wanted to challenge yourself and actually write the code with me then you're more than welcome to follow along with the supplied files i've linked below so let's take a look at the script file let's find mega man let's pop this open so this is the script that i'll make available for you guys and i'll just quickly very quickly run you through it i don't want to make this into like a player controller tutorial video because it's just going to get too long i want this to be very specific to the animation methodology that i'm trying to convey here okay so we've got the animator very importantly we've got a bunch of stuff here just for kind of moving around and ground checks and jump force and things like that um a lot of input stuff so here okay so i've made a bunch of constants to represent the animations in the game um so if we go to animated tab see the names here idle run jump attack all that they are just here as constants this saves us writing out each name over and over and he saves us having typos and things like that and you can most suddenly put these into like an enum i know a lot of people like to do that enums are ways that you can hold different parameters into in like one encapsulated object um but because it's a very beginner friendly tutorial i don't want to get too much into enums right now okay so it's got a rigid body we're mapping an animator we've got a ground mask that we're using for a ground check and in the update loop very lightweight we're just checking the left axes so left and right buttons on the joystick and a amd on the keyboard we have a spacebar check we have a right control keyboard check which is flagging the attack and down in the fixed update as you guys know update is for like input checks fixed update is for actually executing physics and movement and things like that in the fixed update we are just checking for the ground and we are using um is grounded we are flagging that true or false depending on if we can find the ground beneath the player and then we are just creating a velocity holder and we are checking if that x-axis that we mapped in the update is either is pressed left middle or right and then we have is jumped we're adding the force to the jump and then we're mapping the velocity and okay so here we are checking if the attack is pressed we have a check to make sure that is attacking is false before it's true and we're doing that because we don't when we do eventually write this animation code in here we don't want the attack to be overriding itself so let's look at adding these animation play references okay so if we are pressing left if we are pressing right then move the player and if we're not then velocity is zero so here would be a good place to start for the idle we will say change animation state play uh instead our constants are here play idle nice and convenient and if left or right is being pressed then player run and you can put them here like that but we don't like to repeat ourselves in code so what we might do we're going to say if x axis is not equal to zero which means it's being pressed either left or right then change animation shouldn't stay to run and what we can do we can just maybe we just put make an else and move the idle here that's a little bit neater you'll notice that i'm putting this change animation stay logic within the player script you don't have to put it there i'm doing it just for convenience for this video if you wanted to you could make like a separate script called animation manager or something like that then you could talk between the play script and the animation manager and tell it what to do but i don't want to be jumping between too many tabs and windows right now so people don't get confused but yeah you can do it like that if you wanted to all right so if i was to quickly run that as a test cool any blinks boom all right so that's working fine oh and by the way you might be aware that right now there is a huge sale going on on the unity asset store and one of my own assets the ultimate 2d car game kit is part of that sale so if you've ever been interested in making car games this is a great foundation to get into that genre it's got like full mobile support full controller support ready to build sound effects strict physics race systems everything you can think of it's really cool so do check it out it's a fantastic asset that i personally built with a lot of attention and care for you guys to make games with and hopefully make money with two through the app store or steam so now we just need to do the jump so here we are checking for the jump press we're adding force so to say change oh change animation state to player jump okay and that will let the player jump but what we need to do we want to make sure that the idle is not overriding the jump so we need to write a condition over here for that and i'll explain to you just why very quickly i'll run that to show you what the problem will be so jump oh yeah you see that he tries to jump you can see his arms raised and the idle takes over so what we'll do we can wrap this whole thing here we'll say if is grounded and i'll just move this closing bracket over here so only if they're on the ground okay and then if the joystick is moving or not will it respond to those animations otherwise it's just gonna jump cool look at that i'm digging that so at this point we've got three animations without any fancy spiderweb networks or any parameters being sent to the animator or you know set float said bull so we'll wrap this up with the um attack all right so in this condition block here so if the input is being pressed to attack then we want to change animation state to player attack and you see we have two attacks with air attack and a normal attack so we now need to choose betw between which of those we want to do and we'll do that by simply checking if we're on the ground or not say if is grounded so if uh is ground is true then play the normal ground attack else i'll just copy and paste this and we're gonna say player air attack cool that makes sense right so if we're on the ground play a normal attack if we're not on the ground play the air attack so you can see here we have this attack complete that i've just set up and it's all it's doing is setting attack back to false and what that means is because we have this condition here that doesn't actually allow the attack to play more than once until this boolean flag is set back to false so attack will only play if the attacking is not already attacking basically um then after a period of time we want to call this attack complete so to do that for the purpose of just this tutorial i'm going to use an invoke and all this does is it calls another function after a period of time so all you do is pass in the string name which in this case is uh attack complete and then you need to pass in a time after how long should this function be called and as i mentioned you can just kind of hard code in the value like point three but i've actually created a attack delay variable at the top here which i've set to 0.3 and i've serialized that so you can kind of play with it through the inspector to kind of get the best outcome you want but we'll just go back down to there right so what this is going to do is this is just going to after 0.3 of a second it's going to allow us to shoot again so i might just so we just want to also make sure that before the play goes back to an idle state he's also not shooting much like we did with the grounded is attacking so if he's grounded and is attacking is false so we don't want the player to be attacking uh when we make a decision to go back to idle or to run so one problem i have here is um i didn't include the mega man run shoot animation if you've ever played a mega man you'll know that he can run and shoot at the same time i don't have that so he's kind of gonna go back to an idol but the point will be made anyway i think um all right so what if you wanted to map this attack delay to the length of one of these specific animations depending on the kind of game you're making if you're making like a fighting game that has like broad sweeping attacks like a sword then typically you might want to wait for that animation to completely finish playing before then you tell it it can do something else well what you can do is you can say tack delay equals dot get current animator state info then open and close brackets and put in passing a zero and that's an index value so that's returning the current animation that's playing the animator's current animation and then we just simply ask for the length so this attack now delay will return in seconds as a float how long either of these animations are which is really cool because if the attack ground animation and the air animation are different if one was longer than the other then you could wait till they have completely finished to do it like that but in this case we'll just leave it um as this attack value which is like 0.3 if i'm not mistaken okay well that should be it let's check this out now see what happens pretty excited actually so i got the running got the jumping and now we got the view and now jump shoot jump shoot i know there's no bullets guys i know i know but if you want to learn how to do like bullets and stuff like that i have many tutorials that i've already covered this topic in detail so um i'll put links or thumbnails or something for you guys to reference but um yeah for the time being we just have the animation state but look at that guys with the the jump and like i mentioned i don't have the run shoot so that's why he's kind of sliding and shooting um we've got the jump we've got the shoots and it's really cool guys so the most important thing here is that this animator is super clean no crazy links no spider webs and this parameter list is empty no conditions no no shenanigans no malarkey everything is clean and optimal and easy to follow i use these exact same techniques to approach the animation management in my own game blood and mead where i have dozens upon dozens of different situational animations with different condition checks and things like that and it works beautifully you can actually wish list the game on steam at the moment so if you did that that'll be really cool yeah so what i'll do i'll actually make this whole complete project available for all you guys to play with down below so get into it guys and make sure you give the video a thumbs up if you found it useful oh and by the way you can see here the new setup is kind of semi-active i'm still working on a few little kinks and there's this wires running everywhere at this point so that's it all the best on your game dev adventures and i hope to see you all in the next video bye and a huge thank you to all my patreon family here i absolutely love you guys thank you for your support [Music]
Info
Channel: Lost Relic Games
Views: 201,735
Rating: 4.9409356 out of 5
Keywords: 2d player controller, unity 2d tutorial, creating a simple player controller, unity 2d movement, unity 2d character controller, unity3d character controller, player movement tutorial, unity3d, unity2d, indie game developer tips, game development for beginners unity, game developer tip, learn c# unity, indie game dev, intro to c#, how to make an indie game, how to, unity 2d, mecanim, animator, animation state, state machine, blend trees, switch animations
Id: nBkiSJ5z-hE
Channel Id: undefined
Length: 18min 18sec (1098 seconds)
Published: Fri Sep 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.