Monster shadow

VIDEO

Unity Architecture for Noobs - Game Structure

Description:
Unity Architecture is one of those things which can completely overwhelm new devs. This video will introduce you to a handful of architectural design patterns, which shy away from over-engineering, allowing you to learn the basics and get on with developing your game. Simple patterns are perfectly fine for most projects solo devs and small teams set their sights on. Package: https://bit.ly/3JthhfR ❤️ Become a Tarobro on Patreon: https://www.patreon.com/tarodev ========= 🔔 SUBSCRIBE: https://bit.ly/3eqG1Z6 🗨️ DISCORD: https://discord.gg/GqeHHnhHpz ✅ MORE TUTORIALS: https://www.youtube.com/tarodev 0:00 - Intro 0:50 - Hierarchy (Scene structure) 2:17 - Project (Folder structure) 3:00 - Singleton Managers 3:58 - Game Manager 5:47 - Unit Manager 6:12 - Scriptable Objects 8:22 - Persistent Systems 9:18 - Audio System 9:38 - Resource System 10:44 - Unit hierarchy 14:33 - Utilities 15:00 - Rest of Folders 15:18 - That's it (+announcement)
ADD A COMMENT

Tarodev
Few spoken mistakes in this video with corrected annotations. Needed to rush it out before "Merry Christmas" became too irrelevant heh. Love you guys! Enjoy.
Rohan Manchanda
Or you could have just erased the part where you say Merry Christmas? The only thing would be the bush stuck on your head but I think it'll be taken as modern art...
TheSystem
Rather than a State enum, isn't a State object better? No yucky switch statement(s).
Reuben Sandwich
14:55 Anakin approves!
Tarodev
Hah 😂
Leo
Hero type Snorlax 😁
Tarodev
Strongest hero
Simon Lassalle
Hey I was looking for exactly this video for years, so thanks for your advice! I am going to lean towards the "feature" sorting solution :) Would you consider doing a Unity versioning video? I heard that git and LFS are not optimized for this kind of project. Is Collaborate ok?
Tarodev
I've found git to be okay as long as you make everything in your scene a prefab. Changing scene objects seems to be the pain point.
Kasper Grønbak Christensen
This is good advice for new game devs, can recommend 👍
Tube Man
ah yes, destroy children
Zak Kaioken 2
I like to keep my systems inside a static scriptable object singleton so we don't need them to not destroy on load it's just handy to keep things loaded but not in the heirchy pointlessly
Laurynas Pupsta
Great video, but there seems to be a mistake in StaticInstance class On the Singleton class, there should be a return method inside the if (Instance != null) statement. Otherwise, the base.awake method is still being called, and the previously created static instance ref is overriden by the StaticInstance class's Awake method. But still, the structure is amazing. Keep it up!
Tarodev
Yup, you're 100% right. At the time I must have thought Destroy would effectively act as a return (how crazy of me). Thanks for picking that up!
Seizen
Wow, really good video. Most of the videos on YouTube doesn't care about those details you mentioned. Subscribed.
Arconath Resonath
This was something I seriously needed as a self-thought developer, and there are few (maybe no other) examples of architecture out there that's in my league... Thank you very much and you've got a sub.
Pablo Jaén
Why do you use empty objects as separators? If the hierarchy structure is well organized it should not be necessary.
Alex Fu
Awesome video! Inspire me a lot.
Sprungo
This is great content man. There's so much out there for the beginner it's really refreshing to see well made tutorials that cover this intermediate kind of content.
Tarodev
Thanks mate! I'll have some more intermediate to advanced stuff coming shortly!
justcallmedoggie
Thanks for the vid taro!
Tommy Ford
Thankyou so much I've really been looking for something like this :)
Tarodev
You're welcome 😊
Ray
Children Lives Matter mobs be like: "You better refactor that horrible method name right now or else!!!!1!!"
bixarrio
I think your updated Singleton is broken. It will destroy the gameobject if Instance is not null, and then still assign it to Instance. But thanks for this. I've been meaning to create a Singleton base class for years
c6jones720
as a programmer its nice to see this sort of content. Ive seen loads of unity tutorials that amount to clicking a few items in a menu, this leaves me asking the question where is the code to wire it all together?
Tarodev
Here it is baby
anonymous49125
honestly brilliant. I do very similar things but it's refreshing to see such intentionality in a youtube video. another tip is, enums almost always should start with 'Unknown, None, All' --- pretty much comes in handy all the time
Tarodev
That is a great tip because I ALWAYS end up adding it later when I'll undoubtedly need it. At which point I usually assign it a value of -1 or something.
SEE ALL COMMENTS


Transcript:

merry christmas so when i look at my old projects i pretty much just want to
gouge my eyes out and that's not because of the spaghetti code although that is a
little part of it it's just because there's no structure
and structure is something that as you learn as a developer it will adapt and
evolve to your style and it's pretty much always opinionated so something
that you think is awesome someone else will think is just dog
so what i want to do is show you kind of
like what i have evolved over my development career and hopefully save
you a few years of trial and error and get you kind of like into a good uh
structural workflow so that you can start your projects
nice and cleanly so as i said it's very opinionated
but let's just jump straight in so just tidy this up a little okay so let's
start with the hierarchy here so
i like to split mine up into separate groups and i find that no matter what i
put here they will always fit into these five groups so the first one is managers
and what these are uh scene specific like kind of like orchestrated classes
they they control the scene so uh this one will be the flow of the game whereas
this one will be you know managing the units i'll get more into those shortly
in setup is where i put my camera my lights my my event system uh or like a
post-processing volume uh everything goes in setup
just kind of keeps it out of the way environment will be where i am spawning
for example uh like tiles of a grid or uh terrain or trees or anything like
that will go in environment uh sometimes i'll even have a subfolder here that
will be like units and that's where i'll spawn my units under that
and canvases pretty self-explanatory it's just where i put all my canvases uh
usually i have like two or three canvases in a scene
systems are the only objects in my scene that are
using don't destroy on load so i have this one this main object that's
calling don't destroy on load and then i've just got all these sub objects here
uh that are just normal uh static instances uh which i'll go into in a
moment i like to keep all of my don't destroy unload objects my persistent
objects all under one kind of like hierarchy to keep it clean
all right so that's the hierarchy let's go over to uh the project which is the
meats and potatoes and let's go through this one by one so i prefixed my scripts
folder with an underscore and that's just because it puts it up to the top
and scripts is my by far my most commonly used folder so it's always nice
having it up top easy to find now before we get into looking at the uh
code just know that you don't need to understand everything as i'm going
through it okay uh i'm just going to quickly go through the base concepts of
it you should download the project yourself and look through i've commented
pretty much everything so find what you like throw away what you
don't like but the hopes of this is just it's going to help you along your way a
little bit don't worry if you don't understand it as i'm going through it
okay not vital so let's start with the managers we've
got the two here game manager and unit manager as you can see these two
uh correlate to these so let's pop into the game manager
and you can see that it is deriving from a
singleton class which i have down here in my utilities
if we go into it okay so i'm not going to go through exactly what a single tin
is but the base rundown of it is it just allows us to have a single static
instance of this class that we can easily access anywhere
uh well this here is actually more of a just a static instance of the class it's
not exactly a singleton this one here
singleton persistent actually is a singleton because we're ensuring that
there's only one version of this actual object
uh and we're also calling don't destroy unload so persistent as in it's going to
persist through sends [Music]
but yeah as i said just a quick run run through what it actually is sorry back
to our game manager as you can see it's actually inheriting from
that singleton class so basically what a game manager is is a way to manage the
state like the flow of your game if you can see here we've just got this
enum with a with a whole bunch of different states here
and we have this function change state which takes in that enum onstart we call
with the very first state to get the ball rolling
and we we set the state comes down here to
this enum all right what state is it is it starting yes it is let's call this
handle starting here uh we'll do a bunch of stuff here like set up the
environment do some cinematics um and then once we're ready we'll change the
state again to the next state in the in the list which will be spawning
heroes so we'll do the same thing again come down here to spawning heroes uh for
example here i'm calling the unit manager to spawn the heroes once that's
done i'll then go to the next one right and then after this it will be like the
hero's turn the enemies turn and then we might say all right did we
win did we lose if so go to these ones otherwise let's head back to hero turn
and repeat until there is a win condition or a lose
condition so this is just a nice basic enum based
game manager uh which will work for 90 of uh small to medium games
if you're deciding to do like a complex game like if you're setting out to make
gta please don't uh if you are this will have some scaling issues you might want
to look into something like a state machine instead but this is good
honestly for 90 of games that you're probably going to set out as as a single
or small team dev dev team so
a good segue here would probably be get to go to the unit manager so here in our
spawning the heroes we actually call the singleton instance of this unit manager
so that's how you use the uh singleton uh static instance and we spawn heroes
so let's go into there so this is the function and in here
we're just going to spawn one unit and we're going to say we want the tarot
derb unit so then in this
uh function doing a bunch of magic here which i'm
not gonna get into yet i'll come back to it
uh but then as you can see down here like once that's done we then go to the
next state so that's that wraps up the game state manager
okay next is the scriptables folder and in here is just uh where i keep my
scriptable objects if you don't know what a scriptable object is it's just a
class which derives from scriptable objects and that just allows us to
create basically these little data objects here just containers to uh kind
of like pull a bunch of information uh
you can put functions and stuff here but for us we're just using it as a data
container so on this i've just got the faction so
is this a hero or an enemy i've got stats here so stats is a struct
with health attack power and travel distance you might have a whole bunch of
different stats depending on what game you're making but the fact that it's a
struct is very important and i will touch on that a little bit later the the
reason i like to put my stats on the scriptable object and not the object
prefab itself like the spawned unit prefab is because you might want to be
looking through a menu to select units or like a um what are they called like a
monsterpedia or something where where you're looking through all the enemies
you might want to see their stats there and if you're holding them on the actual
uh monster prefab or the unit prefab you have no way to get the stats in like
a proper way right you don't want to spawn the prefab get the stats so now
that it's here we've got access to it in the menus and also when we spawn it in
game we've also actually got a reference to
the prefab uh for the unit which we'll get into a bit later so so that's what
we use to actually spawn the prefab into the game
that's what a scriptable object is so that's our base unit scriptable object
and then we've also got like the actual uh derived class from that so as you can
see it's deriving from the unit base and in this we just as this is a hero we've
got a hero type enum and a nifty little thing with scriptable
objects is you can create asset menu attribute and that what that allows us
to do is right click create and we can actually just click this and it will
allow us to create a scriptable object so we could like
another hero here called snorlax and uh you know fill that out give it some
studies but we won't do that right now
so that's the scriptable objects then we've got our systems here which is
this object down here so we've got our main systems object and this is the only
class that i'm going to inherit from singleton persistent and if you remember
that's just like a singleton class which uh calls don't destroy unload so that we
can put this in the first scene and even after 50
same loads it's still going to be there as well as if you've got if you actually
put this prefab in all uh five different scenes that you've got the first one
will be the only one that ever lives so in the second scene when it comes around
uh it's gonna come down here it's gonna say is is there an instance already
available if there is then just destroy this new instance and uh just keep using
the old instance so yeah that's just the system and it
just sits there uh just acts as our one single don't destroy unload uh kind of
like um master object and then underneath there we've got our audio
system and our resource system so our audio system is just super simple audio
implementation you'll definitely need to expand this but basically it's got uh
play music from this music source and then we've also got play sounds from the
sound source and it takes in a position so you can just uh so you still have
your 3d sound but yeah as i said very simple uh you'll
definitely need to expand it and then we've got our resource system
sorry this is just like one primary repository where you can
keep all the references to your scriptable objects so as you saw here
i'm storing my scriptable objects in resources and then here heroes and then
i've got my scriptable object here so in our resource system i've got a list of
this uh scriptable object type and in a wake i'm calling assemble
resources and the re the fact that it's in resources folder means that we can
actually use resources load all and we're gonna say all right of this type
in this folder which as you can see here and just make a list of them and i also
just like to make a dictionary of them uh using the hero type as the key so now
i can easily just say get example hero taking the type t and just use the key
to quickly look up in this dictionary not too relevant for performance but you
might have a list that's got like 10 000 items so it might be nice to just
quickly quickly grab an item by key so yeah this is just my uh repository
for my scriptable objects and then we've just got these two last folders here so
let's just quickly go through so this is actually how i organize my class
hierarchy for units and this can be also the same for like tiles or uh weapons or
anything you're doing right so first i have a unit base class
and this is the class that every unit will inherit from at its core
so we know that every unit will need stats uh every unit will take damage
right and i've also got this function here set stats so if we go actually go
back to our example unit manager i showed you this before and said i would
come back to it so what we're doing here is we're calling our resource system and
we're using that get example hero function that i made
so now we've got a tarot dev scriptable object so i'm
spawning it uh just using the prefab from that scriptable object if you
remember then i'm grabbing the base stats and as you remember this is a
struct so we're actually creating a new copy of uh the stats here because we do
not want to change the base stats okay that's like set in stone it's always
going to be that way and now that we've got a copy of this
stats object uh struct we can now apply specific modifications to it so as i've
written here it might be like you've taken a potion before a battle or you're
working with a few specific heroes so there's like a good team synergy or
something so i'm just modifying the stats here and then i'm finally calling
the set stats function on that unit uh which then in turn just sets the actual
stats of the unit so that's the unit base then of course we've got our hero
base in our enemy base so the enemy base might have some um ai logic in there
right like because we're obviously not controlling them so they might have you
know do their turn uh that'll be ai then we've got our hero base which
obviously there's no ai here so we're actually controlling this so we'll we
will be listening to like on mouse down have they clicked us have they selected
us uh have they actually executed and tackle or remove so yeah obviously hero
needs different logic than enemies and then also i didn't actually mention this
but in our game manager we've got these two
events here so uh
when we change the state i'm saying on before state change uh and i'm firing an
event and then i'm actually handling the logic here i've found that sometimes you
need it before the state changes and sometimes you need it after the state
changes so i've just added them both and the reason that's handy is because in
our hero unit we want to allow the unit to
move again once it's the hero's turn so we're checking if this new state is in
fact hiro's turn if it is let's set can move to true again right and then once
we actually do the move we'll say can move false and then this will actually
tie in to if you can select the unit again so here as you can see i've got on
mouse down is the current game manager state hero turn if it's not
well it's not time to move so return has this unit already moved if it already
has then return and then if those two checks pass then we can actually like
you know start doing the turn so that's the unit uh the hero base and then
finally we've got the actual hero class so then that derives from hero bass so
then you'll have the actual specific hero logic so if you've got a warrior
you might have a charge if you've got a mage you might have like a
fireball or something you know and just as a quick example of using uh one of
the systems on tarot dev i've got a reference to an
audio clip and then in my start method i'm just referencing the audio system
and playing that sound so you'll see that if you press play
i'll actually do that and also i'm printing out every single
time the state changes so that's the structure that i always
put my units in there's always a base class and then
the faction class basically and then like the specific unit
class cool so that wraps up units now we've just got utilities so utilities
was just the singleton class as you saw here
and also i've got a static class which is helpers and this
is where i'll put just like a whole bunch of useful static and extension
methods so there's one example here which is destroy children which sounds
pretty horrible but we'll give it a transform and then we'll
just loop through its children and destroy them all
so that's helpers and that's all the scripts so let's just close that and
we'll just go through the rest of these folders which is basically nothing audio
self-explanatory prefabs i'll organize it with a nice folder
structure resources that's where we put anything that we want to actually use
resources load with uh so definitely the scriptable objects scenes
and uh sprites all right and that's actually it so uh that was a lot to
digest i know especially as a new dev uh but i hope it helps you streamline your
uh projects and kind of like fill some of the gaps that you weren't too sure on
as i said it's very opinionated take the parts that you like and throw the parts
that you don't but download the project and just go through it at your own pace
and kind of like digest it if you feel like supporting me i've
actually just made a patreon i'm currently sitting at zero patrons
so if you want to support me just head down there um i will be delighted to uh
get pinged that i've got my first patreon so yeah that's it uh i hope you
enjoyed it hope you had fun with me merry christmas and i will see you in
the next video bye [Music]
you