Object References in Unity - How to Communicate Between Scripts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the video today i will be talking about referencing game objects which is a area where a lot of new devs struggle uh so hopefully i can remove some of the guesswork i see a lot of new devs doing these like weird and wonderful tricks to reference their objects well not wonderful they're disgusting so i'll show you what you should really not be doing and then i'll show you what you should be doing and hopefully you'll see the light so i've just got a unit manager here now i'm using a unit manager this could be anything that spawns objects right it could be on the ui you could be spawning buttons you could be uh like a weapon shelf whatever okay i'm just using a unit manager all i've got here is a reference to a game object my unit prefab so that we can start spawning objects so first things first i'll just show you some bad ways to reference game objects so here we've got game object find now if you're a new dev you're probably almost certainly doing this this will search the entire hierarchy for the object called character now computers are fast as hell okay so if you've got like 10 or even 50 objects this is still going to be like blazingly fast even though people will tell you it's slow but really it's a bad way to do it it's it's it's messy okay and the other ways that i'm about to show you are significantly faster same with find object with tag uh it's just not a good way to do things this one here um actually this is incorrect i copy and paste it from the web uh let's just say unit right find objects with type this is one that i do occasionally use all right so this one does have it's rare use case but still you should avoid it if you can do so so i'll get rid of these puppies and let's start uh spawning objects so let's create a spawned obj and this will just be instantiating our unit prefab so that will obviously spawn the object and we'll see that right here called spawn the object uh but now let's say we want to do something with this spawned object here in the update loop right so we need to store a reference to it so we can do that simply by doing this okay so now we've created the private reference of that and we can just come here and we can say uh spawned object transform position equals random uh uh insider units fur so then heading back to unity and pressing play chaos but uh it's doing what we need so now we've got this uh we've spawned this object and now we've got a reference to it and we can use it whenever the hell we want in this class but what if it's not just a game object right like what if we've got this unit here and we've got this unit script okay so uh and let's say on the unit uh we've got a public int level uh variable or something right and we want to actually grab and do something with this level so what i see new devs doing all the time is they store it as the game object and then later on when they need something on the hero they'll do something like spawned object dot get get component and they'll grab the unit and then like they've got access to the level uh but this is a backwards as hell where to do it as unit is a derived from monobehaviour you can simply store it the prefab as a unit and your saved variable as a unit right so now this spawn spawned object is is the unit you can just say spawned object level all right so a little tip i remember when i first began i used to store them as game objects until i realized oh wait a second i'm an idiot and then i started storing them as those but i feel like it's a it's a mistake that every new dev crea makes and just remember now that we're actually storing uh units here and not game objects we'll have to redo the reference here so let's just pull that in cool uh so that's good for one unit what if you're wanting to store a bunch of units right so let's make a private list unit and let's say units and we'll just actually initialize this straight away just to save time and down here we'll go for and we'll do 10 iterations and we'll go units dot add instantiate unit prefab cool so now we've got a list of all of our units um which means we can actually do something with them in update loop so let's do a 4-h loop here units unit and what we'll do is we'll actually take that so this is going to be true chaos i don't know what this is going to look like just one one big shape yeah so now we've got references to all of our units there excellent but what if we want to access these units from an external class let's say we've got a uh like a map manager here but this could be anything you want right and we want to grab our units and do something here let's say we want to actually move our units in the map manager for whatever reason so we have a few choices with the unit manager say a whole bunch of things are wanting to access it if that's the case we could make it a static instance by making it a public static unit manager instance and then uh down here a bit in our awake we could set instance equals to this and if you don't know what a static class is basically it's just going to give us access across our entire code base to this instance here so what's happening is unit manager is being created normally right and then as soon as it starts it's setting itself to this global static instance so now over in our map manager we can do something like unit manager.instance and uh we're not actually exposing anything yet as both of these are private okay so how do we do that well we could make this list here public right we could make this public and let's just rename that to better suit the public convention so then here we can say units right uh unit no that's meant to be units it's a list cool so now we've got access to our units here and we could uh do this like that and that would work fine but this is bad design because uh this class here is what's managing our units right we don't want another class to be able to for example come here and say units equals new list do we and like completely screw up what the hell the unit manager was doing so what we can do is instead of making this public let's actually return this to private cool so let's leave that as is we can do a few things here to expose it we could say public list unit and we could call this units and it just returns units right so this is now a providing a read-only list here so i wouldn't be able to do this now equals new list okay because it's going to say there's no setter available so an alternate way to do this and in my opinion preferable is we can delete that let's make this public again and rename this to units and now we can actually turn this into a ghetto with a private setter so we can just go get and we'll have a private set um and this will be exactly the same as those two lines effectively so here uh it'll still work the same we can't set to it but we can in fact read it uh the the units from the from the list and by the way this here is the same as like just defaulting it i like to actually explicitly have it there so just to demonstrate um no we don't have a map manager so map manager and put the map manager on now you'll see awake will be called the instance will be set map manager will now be able to access all of those units so yeah there you go okay so this is good in the scenario where a whole bunch of different classes are going to be accessing it but what if that's not the case what if you want to keep it a little bit more locked down right well we can use something like a constructor for that and actually send in this reference so if you've only been programming inside unity you probably haven't seen or used constructors all that much so let's just say we've got a public class we'll call this r class in here let's have a property this will be a string of name and then we'll also make a constructor uh which will take in a string name and then in here we'll set name equals name and this is just an example of a constructor if you didn't actually know so we would say r class equals new class and then in here we could say like tarot dev and that would now feed in this into our constructor and it's basically just setting up a class so constructors are just a way to initialize something with a default value uh a default set of values and uh just set up the class in general right in unity with game objects we don't actually have access to a constructor because we're not constructing it ourself we're actually calling instantiate and uh unity does a whole bunch of stuff on the c plus plus side actually spawns the object um and they they would call their own constructors and stuff right so yeah we don't get the actual constructor but what we can do is create our own little constructors pseudo constructors so in here we would have we can't use the actual real constructor as unity will throw a fit but what we can do is we can say public void and i like to call mine init and now here so instead of creating a static instance we could actually give this unit direct access to our unit manager by doing something like this unit manager manager and then manager equals manager right so we're saving we're saving this instance on our class and now here in our unit manager when we're actually spawning our object so let's just grab that and go var unit equals this and then unit.net right and we're sending in our unit manager so we're actually passing the reference into them and then we'll actually add it to the list so now uh our unit has access to this manager but let's just assume this is in here it's still locked down right we're still locking down the unit manager only the things that really need it have access to it so then for example later on here um we could report to the unit manager that we're moving to another waypoint or if we just died we can actually report to the unit manager hey we died uh cleaners up remove us from the list something like that so that's two good ways to reference objects between scripts uh one way is if it's massively asset accessed by a whole bunch of different classes and another way is to keep it nice and um nice and kind of like locked away just passing the the reference to the exact things that need it i do want to show you one more thing on the unit let's say we're doing some collision detection so uh on collision enter right and let's say we're looking for other units so if we're running into another unit we know that it's a unit right because let's say we're doing some uh we're doing some checks here we're saying if collision compare tag oh game object compare tag is on the unit tag or whatever so we're doing these checks um but we don't actually know what scripts are going to be on this unit so let's just assume we're using composition so some units will have a script which will be like um explode on touch another one might have heal on touch or whatever so let's actually do that let's create a script here called uh heal on touch so then in here say we only want to run specific logic if the other unit has heal on touch so what we could do is we could say if uh collision game objects try get component and then in here we can use the out keyword and it will be heal on touch heal on hot cool so now what this function is going to do is it's going to return true or false if it actually if the other script was actually found on this unit okay and it's going to give it to us as an argument using the out keyword so we're checking to see if it's got it if it does then this will run and then like you know heal and touch may have some function called uh public void heal unit something something something so then we can uh go hot dot heal unit or something you know so that's a really nice way to do it um you've probably done it something like this before uh heal on touch and then you'll do something like collision transform get component heal on touch and then you do something like if h does not equal null then let's do this uh but yeah this is just a much nicer way to do it um also uh the other day i completely forgot that this even existed but i accidentally tabbed it out uh what was it uh gameobject.sendmessage right i forgot this existed uh and probably because it's so horrible if you're using send message stop immediately it's not slow or anything i actually benchmarked it it's actually insanely fast but yeah just don't use it this is faster and it's also cleaner and it gives you uh you know type safety and stuff instead of you having to do something like this uh yeah just stop using send message there's literally never a reason for you to use send message but yeah that's it so uh if you're a new dev hopefully this cut some corners for you and filled in some gaps if you're an old dad this probably brought the absolute out of you but yeah like the video subscribe if you're feeling generous and want to support me go over and become a tarot bro on my patreon i'd really appreciate it uh and until then i'll see you next time bye you
Info
Channel: Tarodev
Views: 109,059
Rating: undefined out of 5
Keywords: object references, unity c# script interaction, talk to other scripts, gameobject reference, call function on another script, access another script, unity, unity3d, unity references, unity gameobject, c#, storing gameobjects, unity script interaction, unity c# interacting gameobjects, unity c# gameobject interaction, unity c# interact with scripts, Unity tutorial
Id: dtv7mjj_iog
Channel Id: undefined
Length: 14min 9sec (849 seconds)
Published: Wed Jan 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.