Big plus for using properties with private setter. I see a bunch of Unity tutorials exposing private field as public, and then argue with: "Everyone knows this should be changed only within it's own class".
That part was honestly very confusing because of that. I had no idea what you were talking about until I scrolled down to make a joke about it and saw this pinned comment.
Intermediate dev here, already doing basically everything you showed but this vid taught me how to do some of those things a little better and smarter. Great stuff.
Man, the Instantiate() thing blew my mind. I've been instantiating things as GameObjects and then getting the component for a year now. Glad I clicked on this video and found out there is a shorter path!
The instantiate "as GameObject" thing is/was in the Unity docs, and I think Instantiating is one of the first things a new dev wants to do, so we just do it that way and then never question it ever again...! I didn't... until now. haha
There is still a better way to expose the Units of the UnitManager to other classes. The way you do it, every other class could still call .Add() or .Clear() on the List since you expose the complete List class. Instead you should: private List _units = new List(); public IReadOnlyList Units => _units; This way you can change the _units field only from within the UnitManager, and every other class can only read the units but not change the list at all - thats what the UnitManager is responsible for. Great video!
i have banging my head against the wall for 3 WEEKS. I looked at the API docs, untiy discussions, stackoverflow, other yt vids. I still couldn't get my project to work. YOU ARE A LIFE SAVER
I was about to write something about how it doesn't really translate well when you already have objects preinstantiated in the scene, but then I realized I'm wrong and should never doubt anybody on the internet. Good video.
Total newbie to Unity, but I understood everything you pointed out in the video, and it answered a vexing question in my mind as to how to reference information from one script to another. Thank you.
Amazing! Besides being old or a new dev, this has to do with being self-thought and being exposed to "harmful" tutorials a lot. THIS IS GOLD AND I LOVE YOU AND YOUR BEARD!
Believe me buddy you are helping us more than 100s of youtubers, they only show how to do stuf, you are showing us how to do stuf in the right way. Plz continue making these type of awesome videos
Did your channel is a GOLD MINE. Every video I watch I learn something new and I’ve been using unity for over 3 years. Thanks so much for all the content!
Really valuable video: at 10:28 I sat jaw opened and swear I heard the lyrics to Windmills of your mind "... like the circles that you find in the windmills of your mind .." : ) many thanks.
New dev here - thank you so much! I was struggling so much to find and decide on a clean way to reference between scripts. So good to hear this advice! Can’t thank you enough!
You may not be able to set the Units list when using a private setter, but you can directly manipulate the list itself and since it’s the same reference, you will be modifying the list in the UnitManager. That’s why it’s best to use the readonly keyword or create a copy of the list and return that instead of a direct ref to the list
I don't often write comments, but this video is hidden gem. I have been doing some Udemy game courses and watched countless youtube videos. None of them managed to explain this with same clarity as you. Going a bit fast there, but I slowed down the video and watched it multiple times. Subscribed and checking your other videos now :)
1 year in, Jnr Game Dev working to Intermediate next 2 months, bit nervous as feels like I've barely scratched the surface. You have so much great insight, such a big help. I look forward to all your vids
I've been watching your tutorials for a few months now and most of these ways, I've actually just picked up from your tutorials alone. Kinda cool how you put them all together here so they're easier to see. You just validated the way I've been doing object references. Thank you! I was also always curious why we couldn't use constructors in Unity too, but I guess the Init() thing is the way to go. I try to keep my object reference relationships the same way I do with React web dev---hierarchical and mostly self-contained. But I can't avoid those triangular relationships with classes where child classes need to reference their siblings. I mostly try to just move the data I need for two siblings to the parent to keep them self-contained, to keep that hierarchical structure.
Man I was stuck for 2 days trying to figure out a way to refer a label in my game's main menu UI from a network prefab (Basically making a reference to something upper the hierarchy) and your video saved me. Thank you very much!
Amazing video about intercom between objects, architecture in Unity is definitely one of the toughest subjects to master and do well, thanks for the explanations!
Great stuff right here! There are also *events*! They allow us to structure our architectural dependencies without cycles. And you can have information flow in both ways. This can easily be a dedicated video in on itself.
He is really an awesome instructor in all aspects. To-the-point, brief, simple and with high level of knowledge. And I found his jokes fun. Well most of the time:)
UnityEvents are amazing for decoupling components. You can use them to trigger music, animation, partials, other scrips. It means the code you write about health doesn't need to know about who is should tell, it doesn't know about UI or the rest of the world. This works best in prefabs. Suddenly you can have flexible components that you only couple when you make a prefab
I strongly suggest using System.Action (or delegates if you prefer) instead of UnityEvents. UnityEvents are nice that they can be coupled via the inspector but links can be broken and must be maintained. Whereas, System.Action will be subscribed/unsubscribed at gameObject OnEnable and OnDisable. If you prefer the inspector method, then UnityEvents are quite nice. I'm just of the mind that the less I can couple my references to the inspector then the better.
@@monohybridstudios when the functionality I want is inspector hookups is there a good way to do that with delegates, the main usecase I have is prefabs made of generic components that allow for the game designer to have final say. Eg the interaction component could be used in the chest prefab the npc prefab or interact with more global systems like sound or anything else. that the player can walk up to and interact with. I will agree they get difficult outside of the prefab space or known static objects made in the inspector but still a very useful tool. Further a pure delegate pattern is very helpful in systems that don't touch the inspector
@@monohybridstudios if in doubt make it a designers problem XD in seriousness it's a great way to decouple small behaviour for designers to play with. Making gamejams so much more fun, when the designers gets to play with lego
I work with Unity professionally and these videos are high quality, no nonsense. A design pattern I like a lot and don't even know the name of (don't think it has one) is to add a static List property in a MonoBehaviour. If the MonoBehaviour is called Unit it would look like this: public static List AllUnits { get; private set; } = new List(); The key is to add new objects when they're created or enabled and remove them when they're destroyed or disable. So you'd be adding them in either Start, Awake or OnEnable with List.Add and then removing them in OnDestroy or OnDisable with list.Remove. Which one you choose depends on the behavior you want the list to have -- whether you want disabled things to stay in the list or to be removed from it. Of course there's a bit of extra code needed like making sure you don't add an object more than once and stuff, but that's the gist of it. The end result is that now you have a static list in your code you can access at any time and find all objects that have a Unit component! You can query this list for all sorts of things, like maybe you want to find all your units whose health is < 30 so a healer unit can go to them and heal them or maybe you want all units whose health is > 80 to do an attack. This makes it easy! Of course, I advise programmers NOT to use Linq queries again and again in a game loop and never use them every frame. They can be slow and expensive when it comes to garbage collection if abused. So only use those things at key moments like when the game is starting or loading or every now and again when special events take place. Otherwise, you should write out queries manually in a static method or something using a for loop. Oddly enough, there are some cases where a complex Linq query will actually be faster than an algorithmic query a person writes by hand because Microsoft has optimized the hell out of that type of query. So definitely research and test things you're unsure about -- the nuances can be a bit complicated! In any case, this design pattern I showed here makes it easy to find every object with a certain Component (such as Unit) at any time by simply accessing your Unit.AllUnits list! You can take this a step further by adding the Observer Pattern to things and firing events like an OnSpawn and OnDelete (name them what makes the most sense based on how you're using your objects). Then other classes can subscribe to that event in case they need to know when these things are happening! 🙂
3:40 Maybe I'm wrong, but using getComponent is not a mistake. Your "Unit" is a component of a gameObject (in this case a prefab), it is not the gameObject itself. The Unity editor lets you drag and drop for convenience.
Using a reference on each "Unit"-Object might sound good for readability, but if you have a lot of this units you will have an extra 4 Byte / 8 Byte(on x64) memory on each instance just to keep the same reference. I mean today on modern hardware that sounds not so much but it is actually unnecessary space that you are allocating. The singelton implementation just uses this memory once. Not that the way you are doing it is wrong, its acutally a good design in most of the cases. Just wanted to point that out.
Great stuff. What I have seen so far not only in private projects but even in many Unity tutorials, Unity devs don't know how to structure code, what practices are good or bad or even know base rules of C#.
This is such important info, thank you. I had to rewatch this a few times but once it clicked, it made my sloppy coding much better (I still suck though)
To have a getter for a list, dictionary and even normal array I personally prefer to do this way. public IEnumerable GetUnits() { foreach(var unit in units) { yield return unit; } } So this way no matter if it is a list or an array it will always return the elements.
I love your videos. Would be really helpful to get one talking about different types of event systems. Delegates vs EventHandler vs Action (vs UnityEvents), that sort of thing.
Imo some kind of dependency injection is worth mentioning. Way cleaner than the singleton example, can have different implementations based on build platform or scene that you’re in without polluting the unit manager code or the code of its use cases
Wow wow I am a noob. I did the gameobject storing than grabbing the component / monobehaviour. Thanks! I did the Init(); thing too, but wasnt sure about it if other devs do this too? So great to see you mentioning this aswell. Its great because you can be 100% sure that all required initial processes on the manager are done before calling init() in its targets.
Yeah! I think it is worth mentioning that you should test if "Init()" was run before other logic. Because after the Instantiate, the Awake and OnEnable method runs on the other monobehaviour...
What would be really awesome if you made a video of is a: Damage over Time / Debuff system. There are very few videos/resources about this (only kinda basic ones). Example: * Poison DOT * Fire DOT * Slowness * Stun * And how to increase the durations, damage values of DOTs, damage stacking, etc.
As usual mate, great work in making things so clear and digestible! Even though I feel decent in my programming experience and knowledge I always learn something new from your videos. :)
Takes a bit of getting used to, but you can also use a dependency injection library like Zenject (not affiliated). Saves you from having to wire up all the different references manually. Each class just asks for what they need and it gets given to them by the DI library. This also stops you needing singletons (the static Instance fields), which are generally considered bad practice, since they make unit testing difficult.
@@Tarodev It does, makes life a lot easier in the long run. Making a prototype? Avoid it but making a long term project I couldn't recommend it enough (Zenject
I tried using DI libraries like Zenject but i couldnt found any benefit from using it, idk if thats just because of the bad tutorials i watched, maybe if Tarodev teach us it would make sense.
@@Tarodev I feel like it is the secret sauce I have been missing all this time. Obviously you want a DI Container made specifically for Unity, and it's overkill for a tiny project or a prototype.
@@Tarodev like the good pattern to use depending the kind of games, for example i'm doing a tiny 2d drag and drop game. And i'm using singleton there and i don't know if it's good practice here. That's working fine and well in my project, but maybe there is simple ways. I'll look back at your video as well thanks : )
@@UlricLp Singleton is a widely used programming pattern. That is to say, singletons are not so specific that they work well for one type of game and not for another. If your game reaches a very high level of size and complexity, you might consider adding a tool for dependency injection, but Singletons will always work. Otherwise, there are very few downsides to the singleton which can be summed up as follows: - Don't expose public methods or properties on your singleton that let just anyone mutate them. Only expose publicly what is actually needed, and expose it in such a way that another class accessing the singleton can't modify it. - Singletons don't work well in the context of unit tests. If you have classes that perform critical or complicated or otherwise error prone business logic enough to warrant unit tests, you should make it so that those classes do not directly rely on singletons.
@@UlricLp The thing with design patterns is that they are like blueprints for solving a specific problem or set of problems. If you get good at identifying your requirements and such, you might get a better feel for choosing the right design pattern. Singleton can be fine, but there are caveats: - They introduce dependendencies to other objects which can make it more difficult to do sandbox testing (just throwing enemies into a scene and seeing how they interact with the environment for example - you will always need a valid instance of your singleton in the scene) - A more common issue is the reduced testability. For tests where you check specific methods or procedures, the non-relevant dependencies are often mocked. Meaning that for dependencies to other classes, you might use an interface that will not call the actual singleton in this case, but a proxy class with empty methods. You can use dependency inversion and singleton pattern together though, so you can have a static method or a library where you request a type instance - an interface that your singleton implements - and that method will resolve it to either the actual singleton implementation or something else.
Since you are showing us a lot of cool stuff here, it would be nice if you educated us a little more in terms of how the things you are doing are called. For example declaring a static UnitManager Instance makes this class a Singleton (right?). Not a word on the pro and cons of that? Adding a setter and getter to "Units" makes it a Property. Maybe your audience "should know" those terms, but they are so crucial for Development in general, they shouldn´t just be ignored. Otherwise, very useful code you are showing here, Thanks a lot!
A static reference within that class doesn't mean it's a singleton. You might want to turn it into one (non singleton statics is generally a cursed way to code). Adding a simple Assert.IsNull(instance, "We should be a singleton!") in Awake would do the job.
I look forward to the day I would be bored shitless by this kind of video. Until then, I'm just really happy to see someone that is reinforcing the 80% of what you said that I do know and giving a great intro to the 20% that I didn't know (constructors). This kind of thing should be Unity 101.
@@Tarodev This should be most watched beginner Unity & C# video. I mean people are really getting hard times referencing things when not using the methods u mentioned as start. But that's a point-shot!
Small nitpick, for your 'List Unit { get; private set; } = new List()' the problem with this is that you still expose the Clear(), Add() and Remove() functions to external sources which I can only imagine will lead to unexpected behaviour. If you needed to expose your collection of Units it would be better to do something like 'IEnumerable Units => _units' or even 'List Units => _units.ToList()' but I can't really vouch for the performance of that one (will create a copy of the list). Otherwise good video, love listening along to your content
You're right. I was actually meant to run through a repository pattern in this video so all the list queries are done in the UnitManager, but I completely forgot... That's the risk of these free-form videos where I'm basically winging it :P
You're my favorite Unity youtuber :D. Do you have any plans to go over Scriptable Objects (e.g. the way introduced in the now famous talk from Ryan Hipple?) I didn't see that topic in your channel, but it seems like either lots of devs like to use them everywhere or barely (if at all.) Either way, keep up the great work, you are amazing at clearing up extremely confusing and complicated topics in C# and Unity!
I am coming back to Unity after about a year so this has helped blow away some cobwebs, thanks for that. I would suggest as a side note Events are technically a way to communicate between scripts without dependency at all. I am trying to use more event based logic to prevent reference breakage and dependency issues. I don't know how events compare in terms of performance/speed?
They're perfectly fine and certainly something I should have included in this tutorial... Honestly didn't even cross my mind, lol! But please, only decouple if you need to.
@@Tarodev I was coming here to suggest that might be a better way for the Unit to communicate to the UnitManager, to keep it better decoupled and to avoid the Unit managing the UnitManager. I don’t like child objects telling parent objects what to do…I brought those little buggers into the world, I can take them out.
Excellent overview! Love your videos, man. For me this was a good refresher, but I'm positive this stuff is life changing for any newer dev watching. Keep up the great work!
I just came across an interesting use case that completely contradicted your advice at 3:42! Not saying this to antagonize, but rather to share a funny case of “write code for what you need” and not based on some random advice. I wrote a movement behaviour that expanded some navmesh functionality, and I was using a Waypoint : MonoBehaviour object as the cached reference type. Waypoint is kind of a n-Ary tree node kind of class. But turns out that the moment I wanted to allow for the bots to chase each other and the player, I realised the mistake I made - Had to refactor the entire code to use Transforms instead, otherwise requiring any and all game objects that needed to be chased to have the waypoint component - creating unnecessary memory overhead, and unnecessary complexity. Still needed to access the neighbour nodes in some instances, but a few get components here and there outside of the update loop can’t hurt that much? Oh well Fun times!
Hi Taro, great video! Could you also do a video about tips for visual studio with (or not) Unity? I see your VS is completely different than mine and also responds way faster to intellisense stuff (e.g. errors).
~I'm going to teach you something that you've been trying to comprehend for 30 years, but has alluded you for all of that time.~ "Thank you for trying, but that's Impossible." *Tarodev waves his hands, flips over 4 playing cards, and says "You've got this."* "Whoa! I now know how the stars are ordered and the planets aligned." *Heads over to the Patreon and says "GIVE ME MOAR!!*
For your singleton code in the UnitManager - would it not be slightly better to make Instance a static property with public read and private write? Prevents it being unset outside the class.
I already imagine your room in one year or less looking like Jason Weimann's "Xmas-Tree-All-The-Time" Command Center :D Seriously, that poster looks so lonely there
I use send message. I have a script that detects collisions for instance as a child somewhere, maybe on an arm or leg. And it make it send a OnCollisionArmEnter() message upwards. And it works fine for the relatively speaking occasional send. Kinda set and forget and the script in the parent doesn’t need to go find the dependency or anything. I wouldn’t use it on an update loop though.
Nice video. Do you have any opinions about when to use events (from my understanding: when you have a one-to-many relationship between components/classes, or when you need to check for "changes" you can use them instead of directly polling)? Though, I suppose if you are just subscribing to events, you still need a reference to the object whose event you are listening for. So, maybe a better question is, what are your thoughts on something like an Event Channels/Busses? Have you used them before?
Very helpful video, thanks! Watched video about ObjectPool, and tried understand fiches about Init(), and others. I think I got it well, but this video got me all completely understanding)
Hi! Thanks a lot for this video!! There were quite a few things that I didnt know you could do in Unity and some of them are still not quite clear to me. Initially you define a gameObject prefab, reference it by just dragging it into the SerializedField on the script and then play around with it. Later you change that prefab type from gameObject to Unit which is a MonoBehaviour/class that you defined in another script which is sitting attached to your unit prefab gameObject. In order to reference that Unit object rather than the gameObject itself you do the same thing i.e. drag the prefab gameObject into the SerializedField in the inspector. This is where I am confused a bit. Is Unity smart and it finds the Unit object/Monobehaviour attached to your Unit prefab/gameaobject when you drop it there? For instance, if I created an image and then had a script with a public variable Transform imageTransform would I be able to reference that transform by dragging and dropping the whole Image object into the field? Hope this is not too confusing :D. Secondly, you then go on to instantiate that prefab object by calling Instantiate(Unit). I always thought that you need to instantiate by referencing a gameObject but here you reference your custom object Unit. Is Unity smart and it realizes that it needs to Instantiate the object that Unit script is attached to? Would it be possible to instantiate an object by passing in another component of the object to the Instantiate() call? Say its transform, sprite renderer, etc. Thanks so much and apologies for the long question!
Can you do a video explaining the reasons to use properties instead of public function. I never use properties bc public function to are easier to write and work the same.
I think its more of a preference thing. But properties have the benefit of having everthing at one place. Think of it like this, either you have e private field with getter and setter methodes, or you have e property with the getter and setter right behind or underneath it. In modern coding (not necessarily game dev) you most likely structure you class like this: { private fields public fields constructor properties public methodes private methodes } now place your code bits and you will see they are at least separated by the constructor
Properties are just "the C# way" of writing getters & setters, but you can still write typical getters & setters if you prefer. The methods & properties in this example both serve the same purposes: private int _myInt; public int GetMyInt() { return _myInt; } public void SetMyInt(int value) { _myInt = value; } public int MyInt { get { return _myInt; } set { _myInt = value; } } You mentioned though that properties aren't as easy to write as methods, and if you're writing them like the above example, then you're right. However, you can use lambda expressions to simplify the syntax for both methods & properties like so: public int GetMyInt() => _myInt; public void SetMyInt(int value) => _myInt = value; public int MyInt { get => _myInt; set => _myInt = value; } If you want to make a read-only property, you can shorten it even further like so: public int MyInt => _myInt; There are also auto-properties (but they're not really used much in Unity) that can be defined like this: public int MyInt { get; set; } Which is a one-line equivalent to writing this: private int _myInt; public int GetMyInt() { return _myInt; } public void SetMyInt(int value) { _myInt = value; } Auto-properties can also be defined as follows: public int MyInt { get; } //No "set" keyword - the property is read-only. public int MyInt { get; private set; } //private set - can only be set within the same class. public int MyInt { get; protected set; } //protected set - can be set within the same class or inherited classes.
I'm quite new to game dev so perhaps im doing something wrong. In you Video you replaced the Serialized Reference from GameObject to Unit to get around the GetComponent call. Am i right with the assumption this would not work with en Prefab which maybe has several diffrent MonoBehaviour scripts? As an example say i have an Prefab Unit with scripts UnitMaster, UnitMovement and UnitGravity. The UnitMaster is responsible for the referencing stuff like in your video it manages the Init() methode. The other two scripts are i think clear in their responsibility. If i now replace the GameObject with UnitMaster inside the SpawnerManager it wouldn't instantiate the Prefab but only an GameObject with the master Script or am I guessing wrong (havent tryed it in code only thought experiment). What would be the best way to get to the UnitMaster script for something like this?
When I'm using static instances I like to use properties with a setter that throws an error when the class is instantiated a second time. Just to prevent errors. Also I would name the static variable singleton because that's what it is really.
Good to know that someone else cares about new devs, but it's hard to be able to trust someone that does not puts opening curly brackes on new lines. (Damn you javascript!) :P
The "Unit" class is a simple class I created to represent a unit in my game. It's NOT an inbuilt class. Sorry for the confusion
haha thank u bro!! I was googling "unit vs gameObject unity" lol trying to find documentation XD
Big plus for using properties with private setter. I see a bunch of Unity tutorials exposing private field as public, and then argue with: "Everyone knows this should be changed only within it's own class".
That part was honestly very confusing because of that. I had no idea what you were talking about until I scrolled down to make a joke about it and saw this pinned comment.
is Unit the class or the prefab which you are referencing? are they in project? it is so confusing. you are a waste of time
@@coskucimen538 This tutorial is aimed towards slightly higher intelligence levels. You may have better luck learning Scratch :)
Intermediate dev here, already doing basically everything you showed but this vid taught me how to do some of those things a little better and smarter. Great stuff.
same here!
Man, the Instantiate() thing blew my mind. I've been instantiating things as GameObjects and then getting the component for a year now. Glad I clicked on this video and found out there is a shorter path!
The instantiate "as GameObject" thing is/was in the Unity docs, and I think Instantiating is one of the first things a new dev wants to do, so we just do it that way and then never question it ever again...! I didn't... until now. haha
There is still a better way to expose the Units of the UnitManager to other classes. The way you do it, every other class could still call .Add() or .Clear() on the List since you expose the complete List class. Instead you should:
private List _units = new List();
public IReadOnlyList Units => _units;
This way you can change the _units field only from within the UnitManager, and every other class can only read the units but not change the list at all - thats what the UnitManager is responsible for.
Great video!
Yup, great suggestion. Also you could turn your unit manager into a proper repository and just expose api-like functions.
i have banging my head against the wall for 3 WEEKS. I looked at the API docs, untiy discussions, stackoverflow, other yt vids. I still couldn't get my project to work. YOU ARE A LIFE SAVER
I was about to write something about how it doesn't really translate well when you already have objects preinstantiated in the scene, but then I realized I'm wrong and should never doubt anybody on the internet. Good video.
@@sealer1675 a good rule to live by is just believe everything you see on the internet
I have been using Unity for more than one year and never knew about the Instantiate trick, Thanks you !
oh my goodness, this video was just what I needed
that public static Class Instance trick is just beautiful
Total newbie to Unity, but I understood everything you pointed out in the video, and it answered a vexing question in my mind as to how to reference information from one script to another. Thank you.
Amazing! Besides being old or a new dev, this has to do with being self-thought and being exposed to "harmful" tutorials a lot. THIS IS GOLD AND I LOVE YOU AND YOUR BEARD!
Thanks for the beard compliment ❤️
Believe me buddy you are helping us more than 100s of youtubers, they only show how to do stuf, you are showing us how to do stuf in the right way. Plz continue making these type of awesome videos
Did your channel is a GOLD MINE. Every video I watch I learn something new and I’ve been using unity for over 3 years. Thanks so much for all the content!
Really valuable video: at 10:28 I sat jaw opened and swear I heard the lyrics to Windmills of your mind "... like the circles that you find in the windmills of your mind .." : ) many thanks.
You're the best Unity channel out there. I feel like some of the other TH-camrs barely know what they are talking about.
New dev here - thank you so much! I was struggling so much to find and decide on a clean way to reference between scripts. So good to hear this advice! Can’t thank you enough!
You're welcome. So glad I could help you out 😊
@@Tarodev very excited to work my way through all your videos! 😁
You may not be able to set the Units list when using a private setter, but you can directly manipulate the list itself and since it’s the same reference, you will be modifying the list in the UnitManager. That’s why it’s best to use the readonly keyword or create a copy of the list and return that instead of a direct ref to the list
I don't often write comments, but this video is hidden gem. I have been doing some Udemy game courses and watched countless youtube videos. None of them managed to explain this with same clarity as you. Going a bit fast there, but I slowed down the video and watched it multiple times. Subscribed and checking your other videos now :)
Welcome aboard
1 year in, Jnr Game Dev working to Intermediate next 2 months, bit nervous as feels like I've barely scratched the surface. You have so much great insight, such a big help. I look forward to all your vids
I've been watching your tutorials for a few months now and most of these ways, I've actually just picked up from your tutorials alone. Kinda cool how you put them all together here so they're easier to see. You just validated the way I've been doing object references. Thank you!
I was also always curious why we couldn't use constructors in Unity too, but I guess the Init() thing is the way to go.
I try to keep my object reference relationships the same way I do with React web dev---hierarchical and mostly self-contained. But I can't avoid those triangular relationships with classes where child classes need to reference their siblings. I mostly try to just move the data I need for two siblings to the parent to keep them self-contained, to keep that hierarchical structure.
Man I was stuck for 2 days trying to figure out a way to refer a label in my game's main menu UI from a network prefab (Basically making a reference to something upper the hierarchy) and your video saved me. Thank you very much!
Amazing video about intercom between objects, architecture in Unity is definitely one of the toughest subjects to master and do well, thanks for the explanations!
Great stuff right here! There are also *events*! They allow us to structure our architectural dependencies without cycles. And you can have information flow in both ways. This can easily be a dedicated video in on itself.
Took me way too long to find this video. Now I need to do some re-writing. Thanks for this awesome video!
He is really an awesome instructor in all aspects. To-the-point, brief, simple and with high level of knowledge. And I found his jokes fun. Well most of the time:)
Sometimes my jokes can be a little off-base 😂
UnityEvents are amazing for decoupling components. You can use them to trigger music, animation, partials, other scrips. It means the code you write about health doesn't need to know about who is should tell, it doesn't know about UI or the rest of the world. This works best in prefabs. Suddenly you can have flexible components that you only couple when you make a prefab
I strongly suggest using System.Action (or delegates if you prefer) instead of UnityEvents. UnityEvents are nice that they can be coupled via the inspector but links can be broken and must be maintained. Whereas, System.Action will be subscribed/unsubscribed at gameObject OnEnable and OnDisable. If you prefer the inspector method, then UnityEvents are quite nice. I'm just of the mind that the less I can couple my references to the inspector then the better.
@@monohybridstudios when the functionality I want is inspector hookups is there a good way to do that with delegates, the main usecase I have is prefabs made of generic components that allow for the game designer to have final say. Eg the interaction component could be used in the chest prefab the npc prefab or interact with more global systems like sound or anything else. that the player can walk up to and interact with.
I will agree they get difficult outside of the prefab space or known static objects made in the inspector but still a very useful tool.
Further a pure delegate pattern is very helpful in systems that don't touch the inspector
@@rhyspuddephatt Gotcha. I agree. UnityEvents are perfect for handing off the a game designer for use in the inspector!
@@monohybridstudios if in doubt make it a designers problem XD in seriousness it's a great way to decouple small behaviour for designers to play with. Making gamejams so much more fun, when the designers gets to play with lego
I work with Unity professionally and these videos are high quality, no nonsense. A design pattern I like a lot and don't even know the name of (don't think it has one) is to add a static List property in a MonoBehaviour. If the MonoBehaviour is called Unit it would look like this:
public static List AllUnits { get; private set; } = new List();
The key is to add new objects when they're created or enabled and remove them when they're destroyed or disable. So you'd be adding them in either Start, Awake or OnEnable with List.Add and then removing them in OnDestroy or OnDisable with list.Remove. Which one you choose depends on the behavior you want the list to have -- whether you want disabled things to stay in the list or to be removed from it. Of course there's a bit of extra code needed like making sure you don't add an object more than once and stuff, but that's the gist of it.
The end result is that now you have a static list in your code you can access at any time and find all objects that have a Unit component! You can query this list for all sorts of things, like maybe you want to find all your units whose health is < 30 so a healer unit can go to them and heal them or maybe you want all units whose health is > 80 to do an attack. This makes it easy!
Of course, I advise programmers NOT to use Linq queries again and again in a game loop and never use them every frame. They can be slow and expensive when it comes to garbage collection if abused. So only use those things at key moments like when the game is starting or loading or every now and again when special events take place. Otherwise, you should write out queries manually in a static method or something using a for loop. Oddly enough, there are some cases where a complex Linq query will actually be faster than an algorithmic query a person writes by hand because Microsoft has optimized the hell out of that type of query. So definitely research and test things you're unsure about -- the nuances can be a bit complicated!
In any case, this design pattern I showed here makes it easy to find every object with a certain Component (such as Unit) at any time by simply accessing your Unit.AllUnits list! You can take this a step further by adding the Observer Pattern to things and firing events like an OnSpawn and OnDelete (name them what makes the most sense based on how you're using your objects). Then other classes can subscribe to that event in case they need to know when these things are happening! 🙂
tip : use ctorf to create a constructor with the fields
Oh wow. Thank you
Abyss Watcher Boss art on the wall 😍😍😍
One of the most badass bosses of all time
3:40
Maybe I'm wrong, but using getComponent is not a mistake. Your "Unit" is a component of a gameObject (in this case a prefab), it is not the gameObject itself. The Unity editor lets you drag and drop for convenience.
Thanks, I went from almost being able to solve a problem to having no idea what is going on
I hope in a good way?
Using a reference on each "Unit"-Object might sound good for readability, but if you have a lot of this units you will have an extra 4 Byte / 8 Byte(on x64) memory on each instance just to keep the same reference. I mean today on modern hardware that sounds not so much but it is actually unnecessary space that you are allocating. The singelton implementation just uses this memory once. Not that the way you are doing it is wrong, its acutally a good design in most of the cases. Just wanted to point that out.
Tarodev is the best unity channel on youtube, change my mind.
.
.
.
.
you cant
Great stuff. What I have seen so far not only in private projects but even in many Unity tutorials, Unity devs don't know how to structure code, what practices are good or bad or even know base rules of C#.
Not even C# devs do.
They think abstraction is good, decoupling is a universal boon, and that data and behaviour should go hand in hand.
This is such important info, thank you. I had to rewatch this a few times but once it clicked, it made my sloppy coding much better (I still suck though)
Sounds like you're hungry to learn, so keep going and you'll be a pro
@@Tarodev fingers crossed!
The man is a genius
To have a getter for a list, dictionary and even normal array I personally prefer to do this way.
public IEnumerable GetUnits()
{
foreach(var unit in units)
{
yield return unit;
}
}
So this way no matter if it is a list or an array it will always return the elements.
this is an incredibly helpful reference especially for beginners!
Aaaaaah, Unity annexed the C# constructors.
That explains a lot. Thanks!
Tarodev: Making us all better by the video!! 🎉
Finding game objects and getting components since the journey began 😂
Very useful staff! Got some new ideas for my project :) Thanks man
I love your videos. Would be really helpful to get one talking about different types of event systems. Delegates vs EventHandler vs Action (vs UnityEvents), that sort of thing.
Imo some kind of dependency injection is worth mentioning. Way cleaner than the singleton example, can have different implementations based on build platform or scene that you’re in without polluting the unit manager code or the code of its use cases
You're right, I wish I added DI to this video
Wow wow I am a noob. I did the gameobject storing than grabbing the component / monobehaviour.
Thanks!
I did the Init(); thing too, but wasnt sure about it if other devs do this too? So great to see you mentioning this aswell.
Its great because you can be 100% sure that all required initial processes on the manager are done before calling init() in its targets.
Yeah! I think it is worth mentioning that you should test if "Init()" was run before other logic. Because after the Instantiate, the Awake and OnEnable method runs on the other monobehaviour...
What would be really awesome if you made a video of is a: Damage over Time / Debuff system.
There are very few videos/resources about this (only kinda basic ones).
Example:
* Poison DOT
* Fire DOT
* Slowness
* Stun
* And how to increase the durations, damage values of DOTs, damage stacking, etc.
Sorry to jump in but I've got a video on my channel about creating a magic system in unity using scriptable objects that covers some of this stuff
@@DanPos Dan saves the day!
Hope it's not too cheeky to do so
Excellent video, this is exactly the type of stuff I need! Would love a coaching session perhaps in the future xD
As usual mate, great work in making things so clear and digestible! Even though I feel decent in my programming experience and knowledge I always learn something new from your videos. :)
ty for all the vids, PLX dont stop doing! i'm learning so much!
Takes a bit of getting used to, but you can also use a dependency injection library like Zenject (not affiliated). Saves you from having to wire up all the different references manually. Each class just asks for what they need and it gets given to them by the DI library.
This also stops you needing singletons (the static Instance fields), which are generally considered bad practice, since they make unit testing difficult.
You know, I use so much DI in my dayjob, but never use it in game dev. Does it translate well?
@@Tarodev It does, makes life a lot easier in the long run. Making a prototype? Avoid it but making a long term project I couldn't recommend it enough (Zenject
I tried using DI libraries like Zenject but i couldnt found any benefit from using it, idk if thats just because of the bad tutorials i watched, maybe if Tarodev teach us it would make sense.
@@Wobling I'll jump in and take a peak
@@Tarodev I feel like it is the secret sauce I have been missing all this time. Obviously you want a DI Container made specifically for Unity, and it's overkill for a tiny project or a prototype.
Also i'd love to have your input about design patterns in Unity
More advanced patterns? If you're after beginner ones I just did a video on a few :)
@@Tarodev like the good pattern to use depending the kind of games, for example i'm doing a tiny 2d drag and drop game. And i'm using singleton there and i don't know if it's good practice here. That's working fine and well in my project, but maybe there is simple ways. I'll look back at your video as well thanks : )
@@UlricLp Singleton is a widely used programming pattern. That is to say, singletons are not so specific that they work well for one type of game and not for another. If your game reaches a very high level of size and complexity, you might consider adding a tool for dependency injection, but Singletons will always work.
Otherwise, there are very few downsides to the singleton which can be summed up as follows:
- Don't expose public methods or properties on your singleton that let just anyone mutate them. Only expose publicly what is actually needed, and expose it in such a way that another class accessing the singleton can't modify it.
- Singletons don't work well in the context of unit tests. If you have classes that perform critical or complicated or otherwise error prone business logic enough to warrant unit tests, you should make it so that those classes do not directly rely on singletons.
@@UlricLp The thing with design patterns is that they are like blueprints for solving a specific problem or set of problems. If you get good at identifying your requirements and such, you might get a better feel for choosing the right design pattern. Singleton can be fine, but there are caveats:
- They introduce dependendencies to other objects which can make it more difficult to do sandbox testing (just throwing enemies into a scene and seeing how they interact with the environment for example - you will always need a valid instance of your singleton in the scene)
- A more common issue is the reduced testability.
For tests where you check specific methods or procedures, the non-relevant dependencies are often mocked. Meaning that for dependencies to other classes, you might use an interface that will not call the actual singleton in this case, but a proxy class with empty methods. You can use dependency inversion and singleton pattern together though, so you can have a static method or a library where you request a type instance - an interface that your singleton implements - and that method will resolve it to either the actual singleton implementation or something else.
@@fmproductions913 hey thanks for your awnser and clarification about singletons here ! :)
Thanks for covering these topics in some of the recent video. It's on point and done well!
You're welcome Aj
Since you are showing us a lot of cool stuff here, it would be nice if you educated us a little more in terms of how the things you are doing are called. For example declaring a static UnitManager Instance makes this class a Singleton (right?). Not a word on the pro and cons of that? Adding a setter and getter to "Units" makes it a Property. Maybe your audience "should know" those terms, but they are so crucial for Development in general, they shouldn´t just be ignored. Otherwise, very useful code you are showing here, Thanks a lot!
A static reference within that class doesn't mean it's a singleton. You might want to turn it into one (non singleton statics is generally a cursed way to code). Adding a simple Assert.IsNull(instance, "We should be a singleton!") in Awake would do the job.
I was literally googling this today to have a good optimized scripts xD
anyway you are my savior
Awesome stuff man, I really appreciate the quality of your content! :)
I look forward to the day I would be bored shitless by this kind of video. Until then, I'm just really happy to see someone that is reinforcing the 80% of what you said that I do know and giving a great intro to the 20% that I didn't know (constructors).
This kind of thing should be Unity 101.
Tarofangay here. Thanks for the great video! Gonna watch & take notes from everything you mention.
Enjoy buddy, thanks for the suggestion
@@Tarodev This should be most watched beginner Unity & C# video. I mean people are really getting hard times referencing things when not using the methods u mentioned as start. But that's a point-shot!
Very helpful. Unity Learn touched on this but didn't give this style of example to see how it works.
I loved the opening bro, thanks for the video. It's all good information for beginners.
Not gonna lie, some big brain tips here.
Thank you taro ❤️
Small nitpick, for your 'List Unit { get; private set; } = new List()' the problem with this is that you still expose the Clear(), Add() and Remove() functions to external sources which I can only imagine will lead to unexpected behaviour.
If you needed to expose your collection of Units it would be better to do something like 'IEnumerable Units => _units' or even 'List Units => _units.ToList()' but I can't really vouch for the performance of that one (will create a copy of the list).
Otherwise good video, love listening along to your content
You're right. I was actually meant to run through a repository pattern in this video so all the list queries are done in the UnitManager, but I completely forgot... That's the risk of these free-form videos where I'm basically winging it :P
You're my favorite Unity youtuber :D. Do you have any plans to go over Scriptable Objects (e.g. the way introduced in the now famous talk from Ryan Hipple?) I didn't see that topic in your channel, but it seems like either lots of devs like to use them everywhere or barely (if at all.) Either way, keep up the great work, you are amazing at clearing up extremely confusing and complicated topics in C# and Unity!
Yea, that obj.GetComponent() mistake is one that is taught a lot as a way to do it.
Lot's of useful tips , thankyou!
Thank you, new dev. Super informative. Subbed!
Merci Beaucoup!
I discovered your channel a few days ago, I'm learning a lot of interesting things. I'm drugged now :). Continue your great job.
All drugged up and feeling good?
@@Tarodev yes everything is fine, just a few hallucinations where I see you in a cat or in a sponge bob
I am coming back to Unity after about a year so this has helped blow away some cobwebs, thanks for that. I would suggest as a side note Events are technically a way to communicate between scripts without dependency at all. I am trying to use more event based logic to prevent reference breakage and dependency issues. I don't know how events compare in terms of performance/speed?
They're perfectly fine and certainly something I should have included in this tutorial... Honestly didn't even cross my mind, lol!
But please, only decouple if you need to.
@@Tarodev I was coming here to suggest that might be a better way for the Unit to communicate to the UnitManager, to keep it better decoupled and to avoid the Unit managing the UnitManager. I don’t like child objects telling parent objects what to do…I brought those little buggers into the world, I can take them out.
@@MarkRiverbank Hahaha!
Excellent overview! Love your videos, man. For me this was a good refresher, but I'm positive this stuff is life changing for any newer dev watching. Keep up the great work!
It would have saved me a lot of time if I had seen this earlier
I should have gone to greater lengths to get this in front of you, apologies 🙏
I just came across an interesting use case that completely contradicted your advice at 3:42! Not saying this to antagonize, but rather to share a funny case of “write code for what you need” and not based on some random advice.
I wrote a movement behaviour that expanded some navmesh functionality, and I was using a Waypoint : MonoBehaviour object as the cached reference type. Waypoint is kind of a n-Ary tree node kind of class.
But turns out that the moment I wanted to allow for the bots to chase each other and the player, I realised the mistake I made - Had to refactor the entire code to use Transforms instead, otherwise requiring any and all game objects that needed to be chased to have the waypoint component - creating unnecessary memory overhead, and unnecessary complexity.
Still needed to access the neighbour nodes in some instances, but a few get components here and there outside of the update loop can’t hurt that much? Oh well
Fun times!
Hi Taro, great video!
Could you also do a video about tips for visual studio with (or not) Unity? I see your VS is completely different than mine and also responds way faster to intellisense stuff (e.g. errors).
He does not use VS he uses rider. Its a paid IDE and the best.
Great and informative video as usual!
~I'm going to teach you something that you've been trying to comprehend for 30 years, but has alluded you for all of that time.~
"Thank you for trying, but that's Impossible."
*Tarodev waves his hands, flips over 4 playing cards, and says "You've got this."*
"Whoa! I now know how the stars are ordered and the planets aligned."
*Heads over to the Patreon and says "GIVE ME MOAR!!*
Best openining maker
Glad somebody appreciates it :D
Love your videos. Get to learn something different about coding in each one
Whoa that keyboard must be on fire, noice
Really great video, I learnt alot! legend
thx. a great tutorial for beginners. There was overcoocked 2 ost background of the tutorial. xD
Amazing video! I found it extremely useful and it is even more useful for beginners.
For your singleton code in the UnitManager - would it not be slightly better to make Instance a static property with public read and private write? Prevents it being unset outside the class.
I already imagine your room in one year or less looking like Jason Weimann's "Xmas-Tree-All-The-Time" Command Center :D Seriously, that poster looks so lonely there
I use send message. I have a script that detects collisions for instance as a child somewhere, maybe on an arm or leg. And it make it send a OnCollisionArmEnter() message upwards. And it works fine for the relatively speaking occasional send.
Kinda set and forget and the script in the parent doesn’t need to go find the dependency or anything.
I wouldn’t use it on an update loop though.
Nice video.
Do you have any opinions about when to use events (from my understanding: when you have a one-to-many relationship between components/classes, or when you need to check for "changes" you can use them instead of directly polling)? Though, I suppose if you are just subscribing to events, you still need a reference to the object whose event you are listening for. So, maybe a better question is, what are your thoughts on something like an Event Channels/Busses? Have you used them before?
Very helpful video, thanks! Watched video about ObjectPool, and tried understand fiches about Init(), and others. I think I got it well, but this video got me all completely understanding)
Kinda nice to see a fellow Rider user 😅
Hi! Thanks a lot for this video!! There were quite a few things that I didnt know you could do in Unity and some of them are still not quite clear to me. Initially you define a gameObject prefab, reference it by just dragging it into the SerializedField on the script and then play around with it. Later you change that prefab type from gameObject to Unit which is a MonoBehaviour/class that you defined in another script which is sitting attached to your unit prefab gameObject. In order to reference that Unit object rather than the gameObject itself you do the same thing i.e. drag the prefab gameObject into the SerializedField in the inspector. This is where I am confused a bit. Is Unity smart and it finds the Unit object/Monobehaviour attached to your Unit prefab/gameaobject when you drop it there? For instance, if I created an image and then had a script with a public variable Transform imageTransform would I be able to reference that transform by dragging and dropping the whole Image object into the field? Hope this is not too confusing :D. Secondly, you then go on to instantiate that prefab object by calling Instantiate(Unit). I always thought that you need to instantiate by referencing a gameObject but here you reference your custom object Unit. Is Unity smart and it realizes that it needs to Instantiate the object that Unit script is attached to? Would it be possible to instantiate an object by passing in another component of the object to the Instantiate() call? Say its transform, sprite renderer, etc. Thanks so much and apologies for the long question!
Hey, thanks for thoses really cool tips and example !
Cool! But can you do the same thing but one step forward using zenject?
Great content, keep it coming!
Can you do a video explaining the reasons to use properties instead of public function. I never use properties bc public function to are easier to write and work the same.
Same here. Idk if it's more of a preference thing but I like the readability of just using public functions as Getters and Setters when I need to.
I think its more of a preference thing. But properties have the benefit of having everthing at one place.
Think of it like this, either you have e private field with getter and setter methodes, or you have e property with the getter and setter right behind or underneath it.
In modern coding (not necessarily game dev) you most likely structure you class like this:
{
private fields
public fields
constructor
properties
public methodes
private methodes
}
now place your code bits and you will see they are at least separated by the constructor
Properties are just "the C# way" of writing getters & setters, but you can still write typical getters & setters if you prefer.
The methods & properties in this example both serve the same purposes:
private int _myInt;
public int GetMyInt() {
return _myInt;
}
public void SetMyInt(int value) {
_myInt = value;
}
public int MyInt {
get {
return _myInt;
}
set {
_myInt = value;
}
}
You mentioned though that properties aren't as easy to write as methods, and if you're writing them like the above example, then you're right.
However, you can use lambda expressions to simplify the syntax for both methods & properties like so:
public int GetMyInt() => _myInt;
public void SetMyInt(int value) => _myInt = value;
public int MyInt { get => _myInt; set => _myInt = value; }
If you want to make a read-only property, you can shorten it even further like so:
public int MyInt => _myInt;
There are also auto-properties (but they're not really used much in Unity) that can be defined like this:
public int MyInt { get; set; }
Which is a one-line equivalent to writing this:
private int _myInt;
public int GetMyInt() {
return _myInt;
}
public void SetMyInt(int value) {
_myInt = value;
}
Auto-properties can also be defined as follows:
public int MyInt { get; } //No "set" keyword - the property is read-only.
public int MyInt { get; private set; } //private set - can only be set within the same class.
public int MyInt { get; protected set; } //protected set - can be set within the same class or inherited classes.
@@Dxpress_ I agree lambda s are awesome.
Nice, thank you. I feel like this was targeted right to me and where I'm at right now with Unity/C#, and what I'm struggling with.
Blew my mind when you stored the unit as a Unit script and not a GameObject and didn't need to get any components. I fell for that too :(
Great video man.
I'm quite new to game dev so perhaps im doing something wrong. In you Video you replaced the Serialized Reference from GameObject to Unit to get around the GetComponent call. Am i right with the assumption this would not work with en Prefab which maybe has several diffrent MonoBehaviour scripts?
As an example say i have an Prefab Unit with scripts UnitMaster, UnitMovement and UnitGravity. The UnitMaster is responsible for the referencing stuff like in your video it manages the Init() methode. The other two scripts are i think clear in their responsibility. If i now replace the GameObject with UnitMaster inside the SpawnerManager it wouldn't instantiate the Prefab but only an GameObject with the master Script or am I guessing wrong (havent tryed it in code only thought experiment).
What would be the best way to get to the UnitMaster script for something like this?
You can save a prefab reference by any component the object has. Generally you pick the one which will be used most often
@@Tarodev so it would work with prefabs, I must try this. Thank you 😁
Awesome content (AGAIN) thank you!
Great Content !! , thanks for all the Videos :)
Sometimes I Like To Have Unity Tutorial In The Background Even If I Already Know How To Do Them :P
When I'm using static instances I like to use properties with a setter that throws an error when the class is instantiated a second time. Just to prevent errors. Also I would name the static variable singleton because that's what it is really.
Jon's Skeet "C# in Depth" have a good examples for this pattern including thread-safe implementetion.
Good to know that someone else cares about new devs, but it's hard to be able to trust someone that does not puts opening curly brackes on new lines. (Damn you javascript!) :P
lol! Only heathens put curlies on new lines.
Thanks man, great videos!