How to Use Actions in Unity [Unity Tutorial]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi guys mike here from comp3 interactive welcome back to the channel today we're going to be talking about actions we're going to talk about what they are why they're useful why we'd prefer to use them over other patterns like singletons and i'll show you a few examples in-game of those working as well so first of all what is an action well an action is basically a delegate and an event now you can declare those separately and create your own individual action but for this instance we're just going to use the built-in c-sharp action and the reason i'm choosing to do that is because nine times out of ten that's all you need it's less work on your end and you end up with the same result now if you do want an in-depth tutorial on delegates and events themselves let me know in the comments below and i'll sort that out for you so actually what is an action well the action is basically just an event that when it's triggered anything that's listening to that event can react to it so let's break it down we'll have a action which can be called from anywhere else in our project so we can trigger that action from anywhere now if we want something to happen whenever that event triggers elsewhere in our project usually we'd need a reference to it but in this case we don't so effectively that decouples our chord meaning for example enemies don't need to know about the score system the score system will be on its own independently over in the background the enemies themselves will trigger an event and the score system will listen to that event so effectively we have the action then we have listeners to that action that will react whenever that action is fired and then we have over here on its own elements that are going to trigger that action now this may sound a little bit confusing but the way that i'm going to show you i'm going to use a real in-game example and i'm going to try and make it as simple and straightforward as possible because in reality it isn't actually that difficult and it leads to a lot cleaner code and makes your game a lot easier to maintain and build on so just before we start i just want to thank gigatank 3000 for sponsoring this video i've got his links down in the description below go check him out on twitter go check out his website keep up to date with what he's up to and i also wanted to thank everybody supporting me over on patreon so that's brandon zill steve uk and actually my manager from work raf has just started supporting the channel so big shout out to him i think i deserve a promotion anyway let's get into the examples all right so let's take a quick look at the project that i've got set up here so we have a spawner object which doesn't really have much to do with this it's just so we can actually spawn in some enemies you can see just instantiates the enemy prefab at a set position every second or so so we can close that off we don't care about that we also have a stats manager which currently keeps track of how many kills we've got and puts that out on screen now you've done something like this before or i expect you have it's just the script attached to a text object with a reference to it and every time you call enemy killed it's going to increment the kills and then update the text nothing spectacular we'll jump over to the enemy and the way that i've set this up is a common way that i see people doing things like this now there's nothing wrong with that as such it works but it's by no means the best way of doing it so let's take a look at what i've got we've got a reference to our stats manager inside of our enemy that's a red flag straight away we use find objective type to find the stats manager in the scene whenever we spawn in a new enemy then we just update the position of our enemy so we move along the screen and then whenever we click on it we use that reference to the stats manager and call enemy killed and then destroy the object so as you can see that's gonna work and if i play the game you'll see a enemy spawn in we click on them and we get the score updating perfect it works but now the problem arises if we want to add extra things when we kill an enemy for example i've got a score manager here as well so we pop back over to our enemy if we want to add or update that score we're going to need another reference so that's going to need a private score manager we're gonna need to copy this update the find statement and then inside of our score manager we have update score which takes in an integer so that's going to need to be the score manager dot update score and we'll pass in the variable that we've got up here for the amount of score when the enemy's killed so we've added a lot of extra logic in here and we've also added in an extra reference that we don't need and we've also added in every time a new enemy spawns another find object of type now with only two things this is already getting very hard to maintain so the aim of this tutorial is to decouple the stats manager and the score manager from uh enemy and by decouple i mean we don't want our enemy to actually know about the score manager and the stats manager they're just off in the distance doing their own thing and they're gonna listen for an event when the enemy's killed so i'm just gonna go down here i'm gonna create another c sharp script i'm gonna call this actions you can call that whatever you like going to open this up in visual studio and inside here just going to make a few changes first of all we don't need this to be a mono behavior we're going to make this static so we can call it from elsewhere in our project and we're gonna need to be using the system namespace because the system namespace is where action is held so let's start by creating an action for on enemy killed so we'll make it public so we can access it outside of this class static so we don't need to create a reference of it this is an action and we're just going to call this on enemy killed simple as that so let's start with our stats manager so we still need everything in here we still need to actually update the kill counter we need to update the text and we need our references but we want that to happen automatically when an enemy's killed so we can tap into that action that we've just created and automatically trigger the enemy killed method when that on enemy killed action is triggered and the way that we can do this is by subscribing to the event so i'm going to create an on enable and also an on disable method now these are two reserved methods that are part of the mono behavior of unity and really simply what they do is unable is called whenever an object becomes active and on disable triggers whenever an object becomes inactive so when the object becomes active we want to subscribe to that event so we're going to say actions dot on enemy killed we're going to use the plus equals operator and add in our enemy killed method to it and notice we don't add the parentheses at the end if you do it gives you an error because it's trying to pass a void into an action which is an illegal operation just something to bear in mind so now we've subscribed to it in a on disable we want to unsubscribe and the reason we want to do that is if we have an active reference or an active subscription on a disabled object that object is still technically listening but can't do anything about it so it'll throw an error so that's just something to remember always unsubscribe your events whenever you get rid of that object from the scene so we can save that and that is a kill counter up and running so we pop back over into our enemy script we can start changing things about we can remove our stats manager reference we don't need that which means we can remove it from our start and this time instead of directly calling enemy killed on our stats manager we can call actions dot on enemy killed so now whenever we click on that object our action is going to be called it's going to send out the event and anything that's listening to it is going to get triggered and now in our instance enemy killed inside the stats manager is listening right here so we should be able to play this and everything will work as it did before and it does we can see we also have the score adding 20 every time but we haven't taken that into consideration yet now we'll see how this comes in handy with items that need multiple references so inside of our score manager again we're going to need all of this but we're going to need to copy or retype on enable and on disable but this time we want to subscribe and unsubscribe a score now this time you'll see that we have a problem because update score needs to take in a value of a score to add and currently our action is just a void it doesn't return or accept any parameters so we need to change that and we could just pass in an integer using the angle brackets after action will pass in int but for scalability i always like to pass in the reference to the actual enemy that's been killed itself now that may not be so prevalent in this example but when you expand on this the enemy is going to have more than just a score attached to it that you're going to be interested in so instead of passing through all the different sorts of variables we may as well just pass in the enemy reference as a whole so we can actually pass in the enemy into the action itself and we're gonna need to update a few things here because currently uh on enemy killed isn't being given that enemy parameter so the way around this because we're inside the enemy script we can just pass in this so that'll pass this reference to the enemy script into our action next we'll need to amend our stats manager because now enemy killed doesn't actually match the method signature of our action which is requiring the enemy so we'll just pass in enemy call it enemy ref and we're not actually using it in this but the actual action requires this method to have this method signature so we can just leave everything else as it is now if we pop over to our score manager instead of a int we're gonna pass in again the enemy call that enemy ref again and instead of adding the score we'll get that directly from the enemy reference so that'll be enemy ref dot score when killed which is stored inside our enemy script right here and now that our score manager is actually subscribing to the on enemy killed action we don't need any reference to that whatsoever so we can remove the score manager update score we can remove our start method completely we can remove a reference to the score manager and all we need to do is call actions dot on enemy killed that'll fire off this action now we have two listeners in the scene we have our stats manager which is subscribed to it and our score manager so both of these are going to trigger automatically and update uh on-screen value and if we play the game we'll be able to see that click on our enemies everything works exactly as it did before nice i know you can see in our enemy script we have no reference whatsoever to our stats manager or our score manager so effectively uh enemy doesn't even know about it which is the right way to do it um one final thing that i just want to cover off here you may get some odd errors usually the null reference exceptions if you get that the most common cause is the fact that your action doesn't have any active listeners if you call an action with no listeners it's going to cause an error because effectively it's going to be null so inside of our enemy script where we're calling on enemy killed if we didn't have a stats manager or a score manager in the scene nothing is actually listening to this call so we'll get a null reference exception now there's two ways of doing this is a longer way and a shorter way the most common way is the longer way and that's going to be if actions dot on enemy kill is not equal to null then we'll actually call it but there's a simpler way and as you may have noticed this entire line has been grayed out that's because we can actually simplify this so if we get rid of that if statement and instead what we want to do we'll add a question mark after the end parentheses which is going to do our null check for us so basically the line that we've just removed is replaced entirely by the question mark so if that comes back as it's not null we want to invoke that method so by doing that we'll do dot involved and now the invoke is what needs to take in this we can remove parentheses from the on enemy killed so now this method is only ever going to trigger if there's something listening to it and it isn't null so it's been quite a brief overview of actions but i hope that you can actually see how useful these are in future tutorials i'm gonna try and use these a little bit more often with actual real world examples so you can see just how flexible this kind of system is and how much easier it makes maintaining and scaling your card so i hope you've learned something today i hope you want to subscribe if you do please click that button below click the bell all that standard youtube stuff you know what to do and with that i'll see you again next week thanks for watching guys if you like the content remember to subscribe to the channel for weekly unity tutorials
Info
Channel: Comp-3 Interactive
Views: 3,735
Rating: undefined out of 5
Keywords: comp3, comp3interactive, unity, unity5, unity3d, unity2d, tutorial, game, development, dev, introduction, program, programming, code, coding, csharp, c sharp, c#, games, develop, 3d, 2d, artist, programmer, editor, extension, advanced, multiplayer, how to make a game, how to make games, game development, how to use unity, brackeys, comp-3 interactive, unity 2d, unity 3d, how to make, how to do, game developer, game dev, make money with games, event, delegate, action, actions, listener, event listener, decouple
Id: 8fcI8W9NBEo
Channel Id: undefined
Length: 14min 49sec (889 seconds)
Published: Fri Mar 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.