Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
hello and welcome I'm your KMI and here is my awesome 7-hour free tutorial video All About Learning Unity dots and making an awesome RTS the final game has lots of units lots of buildings and zombies it has resources fog of War ragd dolls destruction zombie hordes and tons more in order to build all this we're going to learn all about Unity dots this is Unity super performing tool stack it can make your code run literally 200x faster that is really insane with this massive speed up you can make more complex more ambitious more interesting games or it simply helps your games hit 60 FPS much more easily or helps keep battery consumption low on mobile so this kind of Extreme Performance has a ton of really awesome benefits we're going to learn all about thatt starting from the absolute Basics starting from literally what exactly is dots what is an entity a component in the system then we're going to learn what is the job system what is the verse compiler and what exactly is the syntax to build all of this we're going to learn about dots physics how to handle authoring and runtime data learn how to do all kinds of queries and tons more so we're going to start coming from scratch and learn each of these dots Concepts one by one slowly bit by bit over the course of about 880 lectures now I worked super hard to make this course have a really nice smooth learning curve based on the comments from students I did achieve that but with that said dots is still very much an advanced topic this is not for beginners if you are a beginner then just stick with game objects and don't worry about dots for now just keep learning the basics and getting n Foundation before learning about dots for beginners you can check out my free catch and chos course on making a game from start to finish all with normal game objects and then a second one on making it multiplayer alternatively you can check out my free shop course if you understand everything in that course for both the beginner and the intermediate sections if so then you're ready to learn about dots or if you've gone through my turn-based strategy course if you manage to go through that one through that entire thing then yep you do have the skills needed to start learning about dots so if you are a beginner then don't worry about dots but if you're not if you're past the beginner stage if you're in the intermediate or advanced level if so then yep I highly recommend you learn about this really awesome tool set like I said the benefits are immense you can run code over 200 times faster compared to normal game objects this allows you to make more complex more ambitious more interesting games so this is definitely a very very powerful tool set that you should know how to use now in this video over here this one this free 7our video this contains the first 7 hours of the course the full course is about 17 hours long so if you want to get the whole thing then check the link description that one contains the full course alongside bonuses like obviously having no ads then the videos are split into separate lectures it also grants you access to my private Discord and my private weekly live streams but over here in this fre video this still has a ton of knowledge I made sure to include as much dots knowledge as possible over here in the first few hours specifically to make this fre video really valuable so even if you can't afford the full course you can still learn how to use dots completely for free with this video I think dots is an absolutely awesome piece of tech I really love what Unity built with it and I really want everyone to be able to learn this awesome Tech it's going to be really interesting to see the games that come up in the next few years as people learn more and more how to work with this so I'm really hoping that this free video helps a ton of people learn how to use this awesome Tech if you want to get the full 17-hour course without any ads to interrupt you and with all the bonuses if so then check the link descript description but if you can't afford then that's fine I hope you learn a ton from this awesome free video and one final request if you find this free video helpful if so then hit the like button and subscribe to the channel it's a small thing but really does help all right so with the intro out of the way let's begin making an awesome RTS and learning all about thoughts so let's start the course in the next lecture hello and welcome I'm your Cod monkey welcome to my Unity dos scor here we're going to learn all about dots which is Unity super Performance Tool stack it requires us to learn a different way it requires to learn about that oriented programming as opposed to object oriented so that requires a different way of thinking and by learning this we're actually going to get some massive performance benefits those will allow us to make games with tons of complexity so you can bring whatever Vision you have to life and despite being a big change changing from o to dood that change is actually not as intimidating as it sounds we're going to start from the absolute basics of dots and slowly step byep increasing complexity so by doing that the UN learning curve will actually be quite smooth and by the end you will have gained an insanely powerful tool that you can use in making whatever games you want to make now like I mentioned in the course page this is not a beginner level course so I'm assuming you're already at the intermediate level I assume you know what is a game object what is a transform I assume you know your way around Unity I assume you know what are generics events and single tends and just basic C knowledge so I assume you are intermediate but when it comes to the topic of dots I will teach everything starting from the absolute scratch since one of the primary goals of dots is to enable massive performance with tons of objects moving around because that naturally one excellent genre for learning about the Ste stack is making an RTS game which is what we're going to do this involves lots of units and lots of logic being applied to lots of objects at once doing an RTS game using Game objects that requires quite a lot of trickery to make it performant whereas over here by using dots as long as we do it properly we're pretty much going to get awesome performance by default in the final game we're going to have tons of units finding tons of zombies we're going to have multiple buildings unit spawning resource Gathering massive zombie hordes we're going to learn how to create flow field pathf finding how to do fog of War how to create a mini map set up zombie building spawner handle shooting melee attacks different unit types and so on we're going to learn how to do dots animation learn about the various fors of dots like how the baking system works and what exactly have structural changes as well as how to combine dots and game objects in various ways so all this all this will be built step by step there is no code written off screen all the lectures also have the downloadable project files so if you get lost at any point you can just download the exact same project files that I'm using and continue from there and as usual I'm always available in the comment section to answer any questions you have so now let's see the final game that we're going to build in this entire course let's see that in the next lecture hello and welcome I'm your Cod Mony here let's look at the finnal game we're going to build throughout this entire course all right so we start off with a super simple main menu this means we're going to handle all about scene loading in dots so let's go ahead and just play and Yep this is our game so we have a bunch of units we have some resources we have an II we've got buttons we've got a mini map we've got special skills so we've got all kinds of things this is an RTS game so naturally we can click to to select and move a whole bunch of units so I can click to draw a selection area and move them around and there you go there are some zombies so as the entities get close enough to a zombie they start attacking they start shooting then the zombies also have some really nice satisfying regnal so as soon as they die they fall down they also have the health bar over there on top of the unit itself so they walk around they deal all kinds of damage then over here we can also see the fog of war in action so we can see there's a persistent dark fog of War so that one has been unexplored whereas if we do explore it and we go back yep now there it becomes xort then the game has a nice hord system so every once in a while we get a hoorde so we can move around and of course we can also spawn some buildings so let's place down a tower this one takes some resources so we can place down a bunch of towers they also have rules so they cannot be placed way too close to one another so they need to be a little bit farther apart so place down a bunch of towers let's prepare for the hord that is coming let's clear off all those zombies and yep here we have the first zombie hard coming this one is pretty simple and another nice mechanic is our special skills so here we have the air strike which is triggered once we kill enough zombies so I can click and there you go and after a while a bunch of helicopters come in they drop a bunch of bombs and there you go everything drops down so if it's a really nice special skill then on the buildings that we can build naturally we can build a Barracks so that is one from where we spawn our units then we can spawn a whole bunch of Harvesters so this one over here this one in L gray this one is actually an iron Harvester except of course we need to be able to afford the cost so we need some gold up there we can see our resources and there's another horde let's actually theend from it so up here here we have a gold node so I can place a gold Harvester place it next to the gold node and there you go the building starts doing construction so it spawns from the bottom and starts going up so it has a nice construction state so it goes and once it gets fully built yep the building also has a view radius so it can see the area around it and there's some nice visual drones to gather around and gather some resources so we can start Gathering that we can start placing down a whole bunch more buildings so let's place down some more gold Harvesters place them all then over there let's defend from this horde the towers themselves they also defend but they also can be destroyed then over here on the barracks naturally we can spawn some units so we can spawn either soldiers or Scouts the scouts deal less damage but they W quite a bit faster so we can spawn either of those and select a bunch of them and prepare for the next sword that is coming in so let's spawn a whole bunch of them we can re Lick in order to give it a different Rally Point so the units are spawning and they're going to come over here let's SP another nice hair strike and boom there you go everything blows up so if we keep finding a bunch of zombies as the hordes keep coming in also naturally the game does have pathf finding so we cannot walk through these walls so the units have to go around it so this using some nice flow field path mining then the buildings also have some nice satisfying destruction so they've got the health as they are destroyed yep there you go they blow up in nice pieces then the ultimate goal of the game is to Simply destroy all the zombies so we need to explore the entire map destroy all the zombies and then we win so there's only a few more zombies so just take them out and as soon as the counter reaches zero y there you go you win and we have controll the entire map all right awesome so Yep this is the game that we're going to build in this entire course we're going to build this all of these mechanics all of this everything step by step starting complete from scratch so we're going to learn how to make all of these awesome RTS mechanics and we're going to learn all the awesome dot stuff that makes all of this game work so now let's see a quick overview of all the steps we're going to take in this entire course so let's see that in the next lecture hello and welcome I'm your cod mck in this lecture we're going to see a quick overview of the entire course so the lectures and all the things we're going to learn and build step by step until the final polish game okay so we're going to start off with a lecture mostly focus on the theory behind dots so what exactly is it what are all the components to it like ECS job system and burst and just basically get a nice overview of the whole tool set before we start using it then we're going to start the section for creating and setting up our project first create the project and install all the packages then we're going to set up our un layout after that set up our Visual Studio then import the first batch of visual SS that we're going to use after that set up the post processing and lighting and with that done we will have our complete setup and in order for you to follow everything exactly the same as I have in this course this is the part where I will tell you to download the project files use so this way use the exact same project as me with everything using the exact same versions that way there is no confusion then we start actually building our game so first learning about dots sub scene baking what is it and how do we convert game objects into entities next we're going to create our first super simple component component and sore some data so we're going to do that and set up our unit structure again all while using normal game objects and the baking system with that done we're then going to create our very first system it's going to be the unit mover system which like name implies we move our unit meaning that at this point we will have seen the basics of entities components and systems then we take that movement system and we're going to refactor it to use dots physics instead of moving the object transform this is super easy to do thanks to the dots Bing system we're going to work with normal physics compon components and everything just works then since this is an RTS game we're going to need the mouse R position so we're going to complete that this is also a super important lecture because it will teach us that not every system needs to be dots we can and we will have normal monab behavior scripts and Dot scripts both them working together then with the mouse position we're going to use that logic to tell the unit to move to the mouse and then here is another super important lecture we're going to refactor our movement code to turn it into a super fast job using the job system we're going to see the actual numbers behind normal mainthread code and super fast Burst enabled multi-thread code the difference is literally 100x next we're going to handle unit selection first just setting up the component to select just one unit and then we're going to be selecting multiple units this means we're going to set up our UI and do some math to be able to draw a selection area and select multiple units this is another great example of interacting with the dot swirl from a normal monab behavior script next we're going to handle selecting a single unit by clicking on it this is another fun lecture because it requires us to learn about dots physics and how to do a dots recast then we're going to generate some move positions for a unit to go to that way they don't all go to the exact same spot this is basically where we can draw our own unit formations next we're going to have a very important lecture learning how to do events in dots this actually really tricky because normally events require objects and delegates so finding a data oriented approach for events is a really interesting challenge then we're finally going to create some zombies to play with create the enemies and Def find what is the concept of a faction after that we're going to build our fine Target system so this system coupled with the concept of factions will work for both zombies and friendly units it won't work for both for finding units of the opposing faction and this also requires us to work with dots physics to find nearby potential targets then we're going to implement the concept of Health create a component to Source some data and systems to handle death then create a visual bullet that we're going to fire set up the component and system to make it move towards the Target in damage next is another really important lecture where we're going to learn all about entity spawning this has some interesting implications with regards to the concept of structural changes after that we're going to polish some things in our shoot logic then set up a simple component and system for spawning zombies then we're going to make them randomly walk around this requires us to learn how to use the random class that is burst compatible which works in quite a different way than you might be used to next setting up a visual health bar this also requires an interesting setup to make sure that the bar is r rendered using the dots renderer and is scaled correctly then we're going to polish up the shooting with some nice lights so this one is a great example of how we can use dots companion game objects after that we're going to implement melee attacks so our zombies will be able to approach our soldiers and damage them then we're going to implement a move override logic this will let us have full control of our units even while they are trying to attack an enemy next is a simple lecture learning about required for update this is how we can define a required component before a system updates so this helps us solve issues with single ton is not existing afterwards we're going to do some refactoring to make our fine Target system always fine the closest Target this is a simple change this lecture is actually a great example of how refactoring is a perfectly normal part of the process first we make Define Target system and then we add some more logic onto it then continuing with targets we're going to implement the logic to lose a Target make it so that if the target is too far it just gets reset then create a simple component to override a Target this allows the player to Target a specific unit regardless of any others being closer and for another Target logic we're going to set the target when hit so when a zombie gets attacked it will Target the unit that attacked it after that is another nice refactoring lecture this one is all about performance all about refactoring normal systems and making them into super fast bursted jobs like I said this is how you should do it first get it working with a simple system for each then refactor it all into a super fast job this lecture is very very important this this kind of refactoring is a core part of dots next we're going to see an important section this one is all about how to create a custom animation system right now dots does not have any animation support so we need to build the system ourselves from scratch this is going to be a fun challenge first we're just going to see an overview of how we're going to implement it and then we're going to start building off the basics preparing everything so we can build upon it next we're going to learn about dots blob assets this is the main way that you can store large amounts of data in an easy to read structure we're going to use blob assets to basically store all of our animation data then we're going to build upon it to store multiple animation data this requires being a little bit tricky with how we set up the blob ENT after that we're going to learn how to change animations on the Fly for example go from Idol to won animation then with that done we're going to implement some events so we can play our animations when they should we're going to implement the idle and won animations and after that we're going to work on the attack animations this is also going to be a tricky one because some animation should be interrupted and some should not after that we're going to do the same thing we've done several times it's time to refactor a normal system into a super fast vers job then with the custom animation system fully working we're going to fix one sneaky issue that always happens it has to do with subscenes and how there are some errors that only show up if the subc is closed so by solving this issue it actually requires us to learn how to make a custom baking system after that for a simple lecture we're going to implement a scout unit this is a unit that is meant to be faster and deal less damage so the really meant for exploration this is going to be an important lecture to learn how our game can support multiple unit types next we're going to create the zombie building spawner zombies are going to spawn from this building with certain rules and they're going to keep spawning until that building is destroyed then we're going to make a friendly building the defensive Tower this one will Target nearby zombies and automatically attack them this lecture is really a great example of the power of dots we're going to build this Tower really quickly thanks to reusing a ton of previously made components and systems next we're going to create a proper scrip ball object to keep track of all of our building types after that we're going to work on a really interesting building the barracks this is where we're going to spawn our units meaning we need to keep track of some kind of unit spawn que which means we're going to learn about dots Dynamic buffers this is how we can store multiple pieces of data in just one dots component then we're going to build a UI for our Barracks add some nice buttons to queue up some units at that point we're going to have multiple buildings working so it's time to work on a building placement manager so we can place down multiple buildings first we're going to handle the logic for the placement and then we're going to build the UI to match we're going to add some buttons so we can select what building we want and then click to place it then we're going to create another building this one is going to be the special HQ building if the zombies destroy this building then it's game over next we're finally going to create a simple camera manager this one won't be made using Sy machine 3.0 it's going to be a nice camera controller where we can move rotate and zoom the camera then another refactoring lecture this one is going to be on fixing some memory leaks after that is another handful of very important lectures that make up the grid system and the path finding section first we're going to see a quick overview of the grid system how we're going to make it work with dots which again that's important then we're going to start implementing that design again making sure it's all data oriented after that we're going to build a nice visual debug this will't be very helpful as we've build the path finding speaking of that we're then going to see an overview of the pathf finding that we're going to implement in this course it's going to be the flow field path finding which has some nice benefits when compared to ASR pathf finding especially when it comes to having tons of units so this is the algorithm that we're going to go in after that we're going to start implementing the pathf finding system write the entire algorithm and make it all work next we're going to make use of our debug visual to make sure it's all working make sure that all the arrows point in the right direction to reach the Target and then of course path finding needs some wall so we're going to add those we're going to do it in such a way that we can easily place them in the editor and they are automatically identified as well as by the algorithm next Once e path is calculated we're going to make our units follow it so first just a quick overview of all the components we're going to build to help us do that and then we start implementing the flow field follower like them implies this one makes a unit follow a certain flow field it just looks at the vector on the grid position under it and follows it until destination after that we're going to apply that logic to multiple units being able to give orders to tell each unit where to go to then another very important lecture this one is all about how exactly do we handle path finding for multiple units to multiple targets if the path cannot be saved this is going to be a tricky one we're going to end up solving this issue by storing multiple flow Fields after that we're going to optimize our path finding in some simple ways we're going to do some rast to basically ensure that we only use path finding when we absolutely need to next we're going to go through all of our code and make sure that all movement is using pathf finding then make sure the underlying flow field gets updated based on obstacles spawning and being destroyed and then another awesome refactoring lecture we're going to take all of our pathline code and refactor it into super fast bursted jobs after that we're going to implement some nice fun RTS mechanics starting off with a mini map units and buildings have icons that show up on the mini map which we can easily see next is another fun mechanic implementing a fog of War this is a pretty interesting one our units have a visibility radius and enemies are only visible inside of it then as units move it also has two pieces of fog of War there's the immediate one and the persistent one so as units explore the map some parts of it become permanently revealed once again the zombies are only visible in the active fog of war after that for some more RTS mechanics we're going to implement the concept of resources and make some buildings Harvest them they need to be placed near resource nodes to start Gathering resources next we're going to put those resources to good use by implementing some cost to our buildings and our units after that we're going to make sure that our buildings have a construction stage they won't take some time to construct instead of just spawning fully constructed right away then we're going to implement a pretty nice horde mechanic this is pretty simple every certain amount of time we're just going to have a massive amount of zombies spawn somewhere in the world and simply attack the HQ next for a really fun lecture we're going to implement some rag dolls this is another tricky one because dots does not support skin mesh renders so we're going to need to be clever to handle this as the enemies die they spawn a r doll and faulted ground in a very satisfying manner then we're going to make a simple main menu doing so requires us to learn how to properly handle multiple scenes and dots this is another interesting question since dots doesn't really have the concept of scenes all systems exist at all times after that we're going to take all of our game elements and make a nice playable map it will have walls resource nodes zombie buildings hordes and a bunch more and then another fun lecture another nice performance refactoring session we're going to use the profiler to figure out how to optimize a bunch of our systems and finally we have the polished lecture this one includes a ton of tiny things things like adding a h dii indicator adding a counter for zombies and zombie buildings adding some screen shakes some building particles some destruction pieces a nice air strike mechanic and a bunch more after all that yep our game will be fully complete and really awesome so as you can see we're going to go step by step from a complet empty project until the final polish game we're going to start from the absolute basis of dots learning how to convert a game object into an entity with the baking system then how to make a simple component and the system to run it learning how to use burst and the job system for massive performance how to use dots physics and a bunch more so little by little we're going to learn more and more about dots in a nice smoth learning curve while also building our really nice RTS mechanics so Yep this is everything that we're going to learn in this course in total 17 hours split across 75 lectures again remember to take your time it really does not matter how long it takes you to go through this course all that matters is that you're learning so take it slow and just just make sure you're understanding everything all right so with all that said let's get started hello and welcome I'm your Cod monkey in this lecture we're going to start with the absolute Basics learning exactly what is dots and what does it do okay so before we begin building the game and writing some code let's first cover the absolute basics of dots just so we're all on the same page now dots or Unity dots that stands for the data oriented technology stack this is a set of Technologies a Unity built which are based on some very specific rules like being data oriented and by following those rules it can provide you an insane amount of performance this was a very ambitious tool set they started working on it back in 2017 and only very recently became production ready the benefits it can provide are definitely imense but they do require a different way of thinking so my goal over here in this course is to teach you that different way of thinking so you can properly use this insanely powerful tool like them implies this is a technology sack meaning it's not just one thing it is actually composed of three separate Technologies the three main ones are the anti component system the job system and and the verse compiler and out of those the enti component system by itself is composed of three things you have entities you have components and you have systems now entities are basically just an identifier entities by themselves have no data no logic nothing at all they're really just a number and nothing else then on those entities you can attach components and components this is what actually stores the data like for example some kind of movement speed and finally you have systems and systems this is what runs Logic on entities that have certain components like for example if you have some kind of unit mover system which looks for entities that have both a local transform and a move speed component the system will cycle through all entities that match those components that have the same components that mention the entity query and then it use the data from those components like the speed inside move speed and the position inside transform it used those to do some kind of transformation on that data so for example in this case maybe grabs some kind of float movement speed from this component and use it to modify the position on the local transform component so this is the core of VCS you've got entities which are just identifiers components which actually holds data and then systems which run Logic on that data another very important part of ECS is actually memory management although you don't need to do this yourself it's all handled in the background but it explains why it's so fast so the reason why ECS is so insanely fast is because in the background Unity is making sure that all the memory is all tightly packed all the components like this is one component type this is another one this another one instead of being split all over across memory instead of that it is all nicely tightly packed all that that is right next to each other which makes it insanely f fast for the CPU to access compared to for example game objects since it follows an objectoriented design you have tons of pointers to different positions in memory so everything is very scattered which makes for very slow CPU access you have for example a game object over here which accesses a position memory for some kind of move speed and it's over here so the CPU has to jump here then has to run some kind of functions that is on a different component so it jumps over here then it accesses some kind of other game object reference so it jumps over here then over here and here and so on so this process of jumping all over the place in memory this one is quite timec consuming it is quite inefficient whereas over here with ECS all the components have their memory packed tightly together so when a system goes to do some Logic on some components the system is literally just jumping from component to component so just one to the other one that is so much faster than jumping randomly around memory also note the specific separation between the components that just hold data and the systems which just run Logic on that data ECS is all about a data oriented design as opposed to objectoriented programming that you're probably familiar with in object-oriented programming you define some kind of object and that object has both data and logic this is what lead some lots of pointers pointing to different positions in memory whereas in ECS with a DAT oriented design with this you have a separation between those two which again leads to faster more tightly packed memory so entities are just identifiers components just on data and systems just run Logic on some data that's it this also means that your code can actually be more modular for example if you have this kind of system let's say say this is a unit mover system this system will move any entity that has a local transform and a move speed component importantly it does not matter what that entity represents it doesn't matter if this represents a single unit or a tank or a building or a bullet if the entity has these two components if so then the system is going to run the same logic on it the system does not care what exactly the entity represents it just runs the exact same logic on all entities that have all the components that match the query we're going to see this in the course how for example we're going to create a fine Target system that system will work for both the player finding targets of the zombies and work for the zombies finding targets of the player so that makes the anti component system the second main part of Dos is the job system this one is all about writing insanely fast multi-thread code meaning run code on multiple threads multiple cores all at once as you might know CPUs nowadays have lots of cores however a lot of game code usually only runs on One Core just one thread so all the other cores they're just wasting time doing absolutely nothing based on that as you can imagine you can gain an insane amount of performance essentially for free by just using those other cores now the reason why a lot of game code uses only one core is because writing multi-thread code is usually extremely difficult you can easily get a ton of errors that are extremely difficult to debug the job system helps solve that by adding a ton of safety nets and a bunch of limitations which in itself makes it much easier to write multi-thread code you simply Define some jobs and cue them up then Unity handles all the complex logic of dependencies and figuring out which thread should work on what job so job system helps you take advantage of the the CPU and all it scores as much as possible you can take the exact same code and literally run it in double or sometimes a 100 times faster because instead of running it all sequentially on just one thread you're going to split it across multiple threads and the third main part dots is the burst compiler now this one is almost a piece of magic it is a special compiler that Unity built which is all about performance just by enabling it you can literally get 100x performance improvements in some scenarios it is truly an insane piece of tech however in order to get those massive speed UPS it has a bunch of limitations the main one has to do with how your code needs to be data oriented as opposed to objectoriented it needs that in order to receive those benefits these limitations are something we're going to learn about in detail in future lectures specifically the difference between value types and reference types so you can't just make every code verst compatible by default but if you keep in mind those limitations then the results you can get by just adding a simple attribute to your code is really quite insane when you combine burst with the job system your code will not only run super fast but run super fast on all cores all at once then when combined with the anti component system which again is all about that oriented design when you use all three you get some really insane results this right here this is an actual example that we're going to build in a future lecture you can absolutely have some normal code that takes 9 milliseconds to execute running that just on a single thread just on the main thread then you can use that code and convert it to use a job and that same code all of a sudden runs at 0.29 milliseconds and then you take that same job and you just apply the verse compatible attribute and with that that exact same code is running on 0.035 milliseconds so you go all the way from 9 milliseconds to 0.35 that is a 260x faster performance Improvement you get all that just by using jobs and the burst compiler now this sounds crazy making the exact same code 260 times faster that does sound insane but that is absolutely real that is how powerful dots can be and it is why you should definitely learn how to use this Tech now these are the three main components of dots but dots also is composed of a bunch more packages for example you've got un physics this is an extremely performant physics system that was built specifically for ECS then you've got collections package this one includes a bunch of data oriented collection meaning things like lists and arrays but that were made to be data oriented instead of object oriented meaning they work with jobs and burst then you've got the mathematics Library this is another package that was built specifically for use with burst so it handles all kind of math operations all of them extremely performant then entities Graphics this is how you can render entities it's also super performant and works with both urp and hrp and net code for entities this is their networking Library meant for for multiplayer games using dots for some super high fast-paced multiplayer all of this together is what is known as dots or the data oriented technology stack and one very crucial thing about dots is how each of these main parts each of these can work by themselves you don't have to use them all for example you can just use the job system and the burst compiler you can just use those two without using entities at all or you can just use entities without using jobs or burst basically these three tools these are distinct separate tools by themselves although of course when combined that's when you get some truly insane results and another extremely crucial thing about dots is always remember that dots is just a tool and it's a tool that can be combined alongside game objects so you can and you should mix and match both game objects and dots you don't have to go full 100% one or the other you can use the right tool to solve the right problem for example in this course we are going to be making an RTS game RTS games are all about tons of units and lots of complex logic so in this case for this game we are indeed going to be making this game let's say about 80% using dots and about 20% using G objects we're mostly going to be using Game objects for the UI and some general manager scripts however you could absolutely do the opposite if you were making some kind of action adventure game you could definitely use game objects for about 80% of your gameplay and use dots just for the 20% that is really performant heavy one of the main benefits of dots is indeed performance so you can build your games using mostly game objects do it just like you're used to just like you're used to building any games and then when you use a profiler and find some hotspots in your game you can use dots just to solve those particular hotspots and again when it comes to dots you can either use entities plus job system plus burst or you can perhaps solve those hotpots by just using the job system and burst without using entities so you can get a ton of benefits by just refactoring some piece of code without having to completely re architecture your entire game so always keep this in mind they can work together dots and game objects dots is really powerful because of that it does not require you to give up all your knowledge of game objects dots is just not a tool in your toolbox it is not a replacement for game objects it is a tool that is extremely good at what it does and as with any tool it is up to you as developer to figure out when and where to use that tool now in terms of learning all about Dots here in this course I will teach you everything needed to build this game I will introduce Concepts like entities systems and jobs I will introduce those as we need them to build the game this is a very practical step-by-step course so instead of learning everything all at once learning just the theory on all the concepts instead of that we are going to learn them as we use them but if you want to get an overview of the entire tools there's two excellent sources that I recommend the first one is unity's official ebook this is an excellent free ebook that has 50 pages it is really detailed it talks a lot about dots specifically this is a highle overview on the theory behind dots how it works all the various components why it's important how exactly it makes the code faster and so on so this very much a high level overview as opposed to a technical guide with very specific implementation details and for a mix of both high level and Technical you can go watch my tutorial on dots in there I focus on teaching how to start using all the technical parts that make up dots so that video is a great very condensed way of learning the entirety of dots like I said in this course I will teach you everything all the components of dots step by step as we need them so you don't necessarily have to go through these two resources personally if I was you I would go through both those just because personally I like first learning a h level overview and then learning the more practical aspects but either way works you can either make a quick pause to go through these resources or just continue following the course either way works up to you okay so now that we know know exactly what is dots and what does it do now it's time to start actually using it so let's begin creating our project and installing packages in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to begin setting up our project and installing all the packages okay so let's begin setting up everything now if you want to follow the course as you go along normally you are supposed to follow along exactly as I do things however for these first few lectures where we are setting up everything it is actually simpler if you just watch these lectures and then later on download the project files that way there are no issues with mismatch versions or anything like that so just watch all the lectures in this section and then download the project files that one contains the entire project then you just unzip that file edit on Unity Hub open it and you'll have everything exactly the same as I have like I said this avoids any issues with version mismatches either Unity version or individual package versions so if you want to follow along definitely wait a bit and then download that but over here in this video and in these following lectures I will show you the whole setup that I did in order to create that project so first of all here I am in unity Hub going to go ahead and create a brand new project for the editor version I'm going to choose Unity 6 then for the template dots can actually work with either urp or hrp let's go with urp because it runs on everything then for the project name let's give some name like do RTS course then select the location the organization in this case we don't need to connect un cloud and that's really it okay so let's create all right so here is our empty un project now let's go ahead and first of all get rid of the urp readme file since we don't really need need those so let's go ahead and just remove okay now let's go ahead and install all the packages that we're going to need so let's go up into window open up the package manager and here let's go inside the UN registry and let's see so the first one is we want to install the entities package so let's scroll down yep there it is the entities package this is the main dots package that contains ECS the entty component system and over here we can also look at dependencies so we can see this one already install a bunch of these ones it will automatically install burst that's the burst compiler it will also automatically install collections this one contains a bunch of native collections like native arrays native lists and so on and it will also install the mathematics Library this is the one that is burst capable which is super fast okay so let's go ahead and install the entities package okay all of those are installed next since we're going to render our entities we also need to install over here the entities Graphics if we don't have this package then we can actually render entities we can't see those visuals so if we want to do that which we do then let's go ahead and install this one okay that one's done as well and since in our game we're going to be using dos physics let's scroll down and find over here the unity physics this is unity's physics system that is built on top of ECS so let's also go ahead and install this one okay that's it and finally let's just go all the way up here and let's also install the 2D Sprite package this basically helps us being able to edit a bunch of Sprites as we import them so we can then use them in the UI and so on so let's go ahead and just install this okay that's it so here if we look in the project here in the project all of these packages are installed so it's really the default ones plus the ones that we we just installed again like I said part of the reason why I told you to wait and then download the exact project files is so you get exactly these same package versions that way there's no confusion about any differences if you download the project you will have exactly this setup okay so that's it all our packages are installed let's close it now let's actually follow the setup that Unity recommends in terms of ID I'm going to be using visual studio Community that's a free version I'm going to talk about that setup in a future lecture now technically you can use whatever ID you want but it has to support Source generation if you look over here inside documentation for the entities package over here we do see a section for ID support and over here it says how this uses the rosling source generators so because this it needs to be using an ID that is compatible with Source generator so in my case like I said I'm going to be using visual studio the community version but if you want you can also use R and that should work as well now interestingly there's no mention over here of Visual Studio code so I don't know if that one is specifically not support maybe it is maybe this one refers to both the visual studio proper and visual studio code but I'm not sure like I said I'm going to be using Visual Studio community so the next important setting is what it says here on domain reload setting for that here in unity let's go into edit then let's scroll down into project settings then on left side here let's go into the editor Tab and now we can scroll down until we find it here it is the enter play mode settings and over here when entering play mode by default it is on this one reload domain and scene and what the docs recommend is do not reload domain or scene so that's it now like it says here this actually has one very important implication basically by disabling the domain reloading any static field or any static events any static that you have will not be reset between runs meaning if you have some kind of static field for an end for some kind of player score and the player's playing the game and they got a score of 50 then you stop playing and you start playing again if you do that when you start playing it will remain with that 50 whereas if you have domain reload enabled it would automatically reset that and when you replay it would once again reset to zero so basically if you're used to using lots of Statics and assuming they reset every time you stop playing that will no longer happen with domain reload disabled so always keep that in mind okay so with that our super basic setup is done our project is pretty much ready to use dots now let's go on to the next lecture and set up our un layout hello and welcome I'm your Cod Mony in this lecture we're going to set up our un layout okay so here we are in our project let's just customize our layout it's very important that you set up your layout in a proper way so that you have easy access to all the things you need and you know where exactly everything is now you can set up the editor in any way you want but it will probably be easier to follow this course if you using the exact same layout as me and like I said since this course is meant for intermediate or Advanced users I am assuming that you know the absolute Basics so I'm assuming you already know what exactly is the inspector window what is the project window the hierarchy window and so on I'm assuming you know what is a game object what is a component transform and so on so I'm assuming you already know all of those absolute Basics now in terms of layout I've been using Unity for over 10 years now I started making my first unity game in 2012 so let's see the unity layout that I've developed over the years versus the Spector over here on the right side this way we always have a nice view of the select object and whatever scripts it has then for the hierarchy I like to grab it and place it down here on the left side we're going to make sure that our scene is always nice and organized so we don't really need the hierarchy to take out tons of space then with the project files over here right next to it with the console also over here on the next tab usually I find that when making the game I want to look at the project window but then when playing I mostly just look at the console soing them in the exact same place but on different tabs that makes perfect sense to me then over here in Center we have the scene View and and with the game tab either over here on the exact same next tab or over onto the side so depending on whether I want to see both them at once I swap it out one or the other okay so the basics this is the rough layout that I normally use now for a couple more options so over here on the project files on the top right corner over here you see these little three dots over here I like to set it as one column layout basically this showcase all the project files all of that in this nice compact list Tre view now if you need to browse lots of visuals in your project files then you can swap back into the other one but for most of the time this compact view works great also since we're here just in case you don't know there's this nice little button over here with an i this basically shows the visibility of the packages so over here we can see we have all these packages installed and if we click on that basically that folder shows up as empty packages still exist they're really just hidden so just small thing in case you want to browse the packages untick this but in most cases probably leave it ticked leave everything nice and collapsed okay that's for the project window then over here for the console for this one let's also go into the three dots for some more options the main one I like changing here is is over here the log entry set it as just one line basically this makes the console nice and compact which personally I prefer you can see a bunch more logs without taking up quite a lot of space then of course if you want to read the whole log you can just click on it and view the whole stack race then if you want you got some more options so show the time stamp or not using monos space font or not you can choose whatever you want I'm going to go with these settings also extremely important is over here these three buttons this is for the tab messages that appear in the console so the left one over here this is info messages basically the regular messages we're going to use this quite a lot next we've got the warnings and then we have errors basically if you un toggle any of these then the messages over here will not show up in the console this is something that a lot of people find quite tricky so if you ever come across an issue where for some reason nothing is showing up in the console definitely make sure you check these buttons always make sure they are all T so you can see exactly every single message then over here on the left side for the clear I like to clear on play just so everything resets then for collapse this one basically collapses messages that are exactly the same into one entry and then just shows a number now personally I don't like this I want to see every single message as it comes even if it is duplicated I've also seen this lead to a lot of confusion for some people they think their code is just firing one message when it's actually firing hundreds So to avoid any confusion leave this un toggled then for pause yep we do want this tck we want the game to automatically pause if some error occurs if you want tole this you might get an error but the game might keep playing which might in turn lead to a bunch more errors so always leave this toggled and that's really it over here for the console then let's go over here onto the game view on the center first over here on the this tab for the free aspect let's swap from free aspect into full HD this is the standard aspect ratio technically this will really only matter when we start working on the UI and positioning elements but either way I like to put it on 16 by9 just as always and then for another very important option over here let's enable vsync basically this will limit the frame rate depending on your monitor's refresh rate this really good to make sure that your graphics card doesn't go crazy trying to render a complete empty scene at like a th000 frames per second this way it won't be limited my case it w limit it to 144 FPS and also if your game view is looking pixelated then make sure you check out this letter if you move it like this then this looks really pixelated so always make sure this one is all the way over to the left okay that's the game View and next to it we have the scene view now for this pretty much on default should be good now over here these two are extremely important definitely make sure you know exactly what these two mean these basically place the handles that you see like for example the move handle if I select something there you go that move handle if it is like this it is placed on pivot but if it is on Center then it's placed on the center of the object usually this is is very confusing so if you ever see your Handles in weird places make sure this one is on pivot that is probably what you want to do then for this one either on local or Global rotation sometimes lobal can be useful if you want to rotate or move something while ignoring the rotation of that particular object but in most cases probably leave it on local then over here let's show the Grid on the y- axis there's no need for snapping and over here all of these also look good so let's leave it on shaded drum mode weit to the disabled sound doesn't really matter for now let's leave all the various effects enabled by default just without the always refresh let's hide hidden objects then for the layers show all of them for the camera everything on defaults and for the gizmos again everything on default okay so here is the layout that I'm going to be using throughout this course like I said it won be easier to follow the course if you're using the exact same layout as me so ideally you should be using this but again all the windows are customizable you can place them anywhere you want so if there is something you absolutely prefer on a different place then go ahead you can drag the windows and place them anywhere you want and once you have a layout that you're happy with go ahead on the top right corner and you can go ahead and save the layout so in this I'm going to save it as the dots RTS course and if you ever get lost you can go ahead you can reload default layout or go back into that one and everything reloads okay great so our layout is all perfectly set up now the next important thing is setting up visual studio so let's continue that in the next lecture hello and welcome I'm your Cod Mony in this lecture we're going to set up our visual studio all right so with the unity layout all set up let's make sure Visual Studio is also set up correctly now over here I'm using visual studio Community 22 this is the free version you can download it directly from their website now you don't have to use the exact same ID that I'm using here technically you can use something else like it says here on the manual you can use whatever ID you want as long as it supports Source generation that's really important since dots does use quite a lot of source generation specifically over here they mentioned Visual Studio 22 plus or rather 21 plus so you can use whatever you want in my case I'm going to be using visual studio 22 Community now let's see my setup for visual studio now I've also included the file with my visual studio settings along with the project files on this lecture so just like with the project files you don't necessarily need to follow everything I'm doing in this lecture step by step you can just download those settings and import them okay so before we actually get into setting up visual studio first actually over here on Unity let's go into window open up the package manager and over here let's just make sure that package is installed so up over here the visual studio editor make sure this package is installed and again your case if you're using jet brains Rider then I'll go ahead and install this package next inside of unity let's go into edit and preferences then over here on the left side let's go into external tools and here make sure you select your external script editor in my case I'm using visual studio 22 then for these extra options if you want to play around reading the source code like for example the source code for dots and so on if you want that then you can go ahead and take these boxes but in our case for this simple game we don't really need to do that so let's just leave them like this and everything is working perfectly so now if I go up here into assets and open up the E project y there you go it does open up visual studio okay great now over here for some more settings again like I mentioned exported all the settings to a file that you can download so here in my visual studio I have a nice extension that adds a bit more colors to my code which makes it easier to read and write and for that extension let's go up here into extension manage extensions then I'm going to search for something called viora y there you go this one like it says here the main thing is that add some brainbow braces so a bunch of colors so everything is easier to see then highlight some keywords and so on so it's a really great thing I believe if you download the settings file it will also automatically install this one but if it doesn't then just go ahead and do this search for PS4 and install it then with that installed let's go into the settings so into tools and let's go into options over here let's scroll down until we find vs4 yep just like this and here are all the settings now I think these are really mostly all the defaults I don't remember if I changed anything but again I'm going to export all the settings I think the main thing that I changed was really just the rainbow braces I think I changed some of these Colors Let's just create an empty script just to see these colors in action so let's just go and let's just right click and create a brand new mon Behavior script let's just call it testing and over here just write a bunch of testing code just to see the colors okay here's some dummy code and yep we can see we do have a bunch of colors so the if is going like that the four like that the ins like that the comment like that the function like that so that's really it now these are really just visuals it's not a requirement so you don't absolutely need this extension but personally I do find quite useful I find it helps make the code a little bit more readable so next for some text formatting rules let's go again into tools into options and then up here let's go into the text editor and again I believe here everything is pretty much default these are the settings again you can just download them or if you want to follow along just pause the video and compare directly with your own I think the only thing that I changed was in one of these so these are the C the scroll bars the tabs the Advan and the code style I think the main change that I did was actually over here on new lines by default C usually has new lines on all these personally I don't like it personally I like to place them the currently braces the opening directly on the same line instead of the new line but again just a personal preference if you like it on new line then you can definitely go ahead and do that okay so like I said I've exported all these settings you can go ahead and download that file directly under this lecture then for importing go up here into tools and then into Import and Export settings then over here click on next then over here let's select import and click on next then if you want go ahead make a backup of your current settings if not then by importing you will override it so I definitely recommend you do this just in case you have your vision Studio set up in some different way if you want to then write some code outside of this course you probably want to get back to your usual settings so make sure you save these then over here on this window click on browse find the file that you downloaded from this lecture so the dots RTS course. vs settings and just go ahead and open that one then click on next and import so with that you should have your vision Studio set up Exel like mine and the other thing is vs for so let's go into tools options then down here scroll down into vs4 then export import click on import settings and again same thing find the file that you download so the Dos RTS course VSS for.xml and just go ahead and import this all right so yep with that you should have your vision Studio set up Exel like mine again again this will avoid any confusion with things being slightly different on your end versus in the video This way everything should match perfectly so y everything is working let's just go back over here inside of unity and let's get rid of our testing script we don't need this okay great so visual sudu is perfectly set up now let's import some visual assets and let's do that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to import the visual assets that we're going to use in the first part of this course okay so here we have our project set up let's import some some nice visual Assets Now the assets that we're going to use those are the ones made by cinty Studios they are an excellent team that makes some really gorgeous low poly assets personally I'm a huge fan of their style I've used in many of my tutorials and in my own game dinky Guardians they have allowed me to use part of their packs in this game and distribute them to you the license for the assets included in this course is you can use them for non-commercial use only so if you want to use them in your own commercial projects you can pick up the entire packs from their store the assets that I selected are from a bunch of their simple series it's a very blocking poly style which personally I felt that it look really great for this game I think it looks really great for an RTS game a lot of assets are from this simple military pack then for a bunch of the buildings I picked them up from the simple space pack and of course for the zombies they came from this simple zombies pack now I really like their style and like I said if you want to use these Assets in your own commercial projects then go ahead and pick up these packs from the cinti store there's links right under this lecture for all the packs and if you like this style then you can pick up the simple bundle this one contains a ton of their assets in this nice style and also by the way the packs that I mentioned those contain a lot more assets than just the ones we're going to use in this course okay so now let's go ahead and download the asset pack for this lecture although again like I said in this section I'm showing all the setup everything that I'm doing but you should really just wait until the end of this section to download the pre-prepared project files so I download the assets and I get this nice ENT package file just double click or drag it onto the project window and up here it is with the asset list these are the assets that we're going to use in the first part of the course later on we're going to import some more assets so over here just make sure you select all of them select all and go ahead and import and if here it is right away we have all of our Assets in our project so we can see a bunch of textures we can see a bunch of meshes and materials and all kinds of things with this we can right away set up a basic scene so first let's actually clean this up a little bit so instead of calling it simple scene let's call the game scene yep then let's right click on the hierarchy let's create a 3D object let's create a plane name this our ground over here on transform let's put it on 0000 0 so right on the origin and for the scale let's make it quite bit bigger let's put it on 40 so 40 on all of them then let's also go ahead and use a ground material so here inside the materials folder we have the ground desert so let's just go ahead and apply this one okay great next for the camera so let's put the game view right side by side for the camera we want a top down view so let's select the camera object and let's position it on 0 29 and minus 25 and for the rotation let's put just 45° over here on the X okay so we have kind of like an overhead view then for the FI The View let's go ahead put it on 40 just like this now let's drag some visuals just for testing so let's go ahead and just drag these meshes so there you go there's a soldier and there's a zombie let's make sure to assign the material so inside the materials folder there's the characters so for the soldier let's assign this material so let's expand that one and assign that material y there it is and for the zombie let's also sign this material all right that should do it so here we have both of our units and they are visible directly over here on the camera okay great so we have our staring assets important so everything is looking nice now let's just handle some more visual things we we want to set up lighting post processing and ssao so let's do that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to set up post processing and lighting to make our scene look really nice okay so here we have some assets and we have our camera set up now let's make it look nice we already have the project set up to use urp so adding post processing is actually pretty simple it's already somewhat enabled by default here this scene that was created automatically already has a global volume and by default it already has a volume profile attached so let's use this as a starting point but let's also just rename it so instead of sample scene profile let's just give it a proper name so the game scene profile okay so now here let's set up the effects although of course keep in mind this really just a visual thing so if you prefer a different visual then feel free to use whatever effects you want now personally I don't really enjoy tone mapping I think it makes it little quite a bit washed out so personally I don't really like it so I tend to remove it then for Bloom we can go ahead and leave it like this so with a threshold of one intensity of 0 25 then for motion blur that is also something I don't like so let's go ahead and remove and for yet I think this one always looks good let's make it just a little bit more intense so maybe some like point4 okay great so that's it for post processing like I said this is just a vision thing so if you want a different look definitely go ahead and use it next thing it's let's set up the lighting so let's go for the main light so on the hierar key let's select the directional light and for this one in terms of temperature it looks pretty good then over here for the intensity let's make it a little bit less intense so 1.5 just like this everything else on defaults next let's hand the global lighting so for that let's go into window then down here let's go into rendering and open up the lighting window okay so here it is let's go onto the environment Tab and on this one over here for the environment lighting for the source instead of Skybox let's go with color and then over here for the ambient color let's make it sort of a grayish white so let's put it maybe some like this so maybe about 220 on all of them yep there you go just like this so that's looking pretty good in terms of lighting and visuals next let's add some nice screen space and inclusion so that one is going to be added on the renderer so let's select the default one and by default it actually comes with a mobile render and a PC render we're making a PC game and this setup for the PC so let's go ahead and use this render this is the one that is actually active and importantly it's over here on the renderer not on the render pipeline asset no for the screen space am inclusion we want it over here on the render and actually already here by default we already have screen space am inclusion let's just make it a little bit more intense since as you can see here the camera is going to be quite far away so for the method I think inter leave gradient look a little bit better then for the intensity let's make it quite a bit more intense so let's say about 10 then for radius let's also make it bigger so 6 follow off distance like this and indirect lighting a bit more like that so as our camera is quite zoomed out I think like this looks quite a bit better we can enable and disable it in order to see the difference so with it disabled and enabled and personally I think it looks quite a bit better with it enabled okay that's great finally let's go onto the render pipeline asset and over here on this one most things are already correct over here let's make sure we have AGR so that Blom works if you want you can go ahead and enable antling MSA either way it shouldn't change too much the important one is down here for the Shadows again since the camera is going to be quite far away we don't want Shadows to dis appear at just 50 units that's way too close so let's put the max distance at some like 150 okay so I think this Vision looks pretty good again like I said most of these visional effects are very much personal preference they don't affect how the code runs in any way also by the way the postcrossing effects like we saw those are actually saved onto a file so if we select the global volume yep here is the game scene profile so if you want you can just duplicate this file then you can have two files with completely different effect settings you can have one that looks Exel like I have here and another one that has whatever effects you want okay that's really it our post-processing effects and everything is all nice and set up so with that let's go on to the next lecture hello and welcome I'm your Cod monkey in this lecture the goal is very simple let's just download the project files and start the project from there this way you have the exact same setup as me with the exact same version numbers everything with the exact same settings everything is exactly the same this is going to help avoid quite a lot of confusion and confusion that I usually see in comments in my courses or tutorials people installing different versions of packages different versions of unity using the built-in render instead of urp and so on so by downloading the exact same project files it will avoid any of those issues so just go ahead and download the exact same project files that I have here on the page for this lecture just scroll down and download the file it is going to be a zip file you can download it and then unpack it somewhere again this contains the entire project so after you unpack it go ahead over here onto un hub click on the little arrow and add project from dis then find the folder and just add it and yep here it is now if you don't have this specific Unity version then you'll see a button over here to download it again use the exact same version as me just to avoid any confusion after you go through this entire course after you learn all of this after words for your own projects you can then use whatever Unity version you want all the knowledge that you'll learn here will apply to pretty much any Unity version so download that add the project and just open it now by the way the first time that you open the project it can take a while basically it's going to download all the packages onto your local machine and after you download everything then you should have this exact same scene here and by the way for the visual studio settings I also added those as downloadable directly on this lecture so if you haven't done that yet then go ahead and do it download these two files and then import them just like covered in the visual studio lecture okay great so you should have this exact same scene open up on your PC with that we can now continue and just before we finish this lecture let's just clean up this scene let's just remove these visual meshes these were just temporary so let's get rid them save the project and that's it all right so our project is complely set up it's time to finally start working with dots so let's do that in the next lecture hello and welcome I'm your Cod mon in this lecture we're going to start learning the basics of dots learn about subscenes and the various dots Windows we're going to create an empty game object and learn about the baking workflow that converts game objects into dots entities okay so here we have our empty project with all the packages installed everything ready to work with dots now the first thing we do is create what is called a subscene so over here on the hierarchy let's right click and let let's go up here create a brand new empty subscene let's call it something like entities subscene and yep there it is so basically this is how you can mix game objects and entities objects outside of this subscene like all of these game objects over here all of these are regular game objects they will not be converted into entities they have nothing to do with dots or ECS or anything like that whereas objects that we place inside of the subscene those will automatically be converted into entities so let's actually see that in action let's right click directly on top of the subs so that whatever we create ends up inside of it and over here let's create a brand new game object and let's just make it a simple 3D cube and if there ises we have a cube directly inside of the subscene and over here we do see it over here on the scene view we do see our game object cube in the game view the camera is indeed rendering that Cube and over here on the inspector we do see the regular components so we have a mesh filter with mesh assigned to it we have the mesh renderer the Box col and so on all of these are normal game object components and of course if we head on play yep everything everything still runs everything is still the same there's our Cube again just like a game object we created using the exact same method and everything looks exactly the same however if we select the cube and over here and look on the inspector if we go down here we see this little thing said the entity baking preview baking is essentially a DOT storm it is the process by which game objects and their game object components are converted into entities and their entity components so it's kind of like making a cake you take some raw dough you bake it and you end up with a cake so dots is kind of like that here we have the normal game object with normal game object components those components are then baked and during the baking process we then end up with an entity that has all of these dots components so down here we are just seeing all the types of the components that we're going to see and by clicking we can actually see some more data in those components and we can also see all this data all at once so on the inspector on the top right corner we have this little circle here here we can basically modify the mode of our inspector so authoring this is what we're seeing right now so it shows us all the authoring game object components so all the normal ones that you're used to seeing but then if we click on it and we swap it into runtime mode yep now here we can see all the empty components and all of their data for example you can see how instead of having a regular transform component instead of that we have a local transform this is a DOT component also by the way if you don't see it that is probably because you went over here on the authoring and you remov this boxer if you do that and now we go back into runtime yep now it does not have the local transform component basically do is pretty smart this baking process is pretty intelligent it will only bake components as they are needed and basically without any physics just an Mt game object this one does not need the local transform component so it does not get it added whereas if we leave that on so let's go here into authoring and let's add the box and Lether back in if we go back there yep now we do see the local transform component and again during the baking process all the data is automatically converted so if we go back into authoring and let's put this on position five three and two and now if we go inside the runtime component y there you go now it does have the exact same position again the process of baking the goal of it is to take the game object components and all of their data and convert them into their equivalent dots components also note how the components do not match one by one so for example over here on the authoring components on the normal game object components we've got transform mesh filter mesh render and box Le so we have four game object components whereas if we go inside runtime to see dots components we can see we have quite a lot more of those this is actually a very important Concept in dots it's how your authoring data can be different from your runtime data later on when we create our own custom authoring components we will be able to have for example one game object component turned into multiple dots components this can be really useful to simplify some things on the authoring side doing that so that it's really easy to build things but then convert into some specific components to make it super fast on the runtime side so this is the baking process this is a really important part to know about dots it's how game object components are directly converted into dots components this system is what makes dots actually surprisingly easy to use for the most part you can actually keep using regular game object components and then everything gets converted into dots components so on that note talking about that conversion let's learn a little bit about what baking is actually doing basically as it takes all of this game object data as it converts that data into dots data as it does that that process is essentially taking all the game object data and converting it into binary dots data so if you look on the hierarchy here if you look inside the subscene we can see how it has this little checkbox here and actually if we click to select the subscene if we look in the inspector we can see how this subscene is actually just a special game object with a special subscene component so even though on the hierarchy it looks like something really special in reality it's really just a game object but anyway so here we have this little checkbox and this one is basally for opening or closing the subscene so right now it is open meaning we can inspect all the objects inside the subscene we can go here we can move it we can modify any of this data and then we can close it or before we do like just hit on Save we have a little sris saying we have unsaved changes so contrl s just to save it and now if we click on this y there you go the sub scene is now closed and now we can no longer inspect the objects that are inside of the subscene the object still exists we can still see it over here on scene View and on game view so the object still exists inside of the subscene but it is now no longer open for editing so what happened here is that object with those game object components all of that was baked directly into binary data and that is the exact same thing that is being loaded directly in here this is exactly why one of the huge benefits of dots is actually World streaming meaning how you can have for example a huge open world and you can have it split into various parts then you can dynamically load and unload each of those parts that's usually how open world games are usually made and the way that dots has a huge benefit in that aspect is because dots works with binary data and binary data is insanely fast to load so the baking process here converting this game object Cube into actual dots binary data that process essentially means that the game does some really heavy processing right now during edit time but then it is insanely fast to load and unload during runtime so like I said this really excellent for creating huge open worlds you can split a giant world into multiple subscenes and then very easily dynamically load and unload those scenes as the player moves throughout that world so right now with the subscene close right now we cannot edit our objects with its authoring data so here in the hierarchy it does not even show up however dots also has some entity specific windows so let's go here up top into the window menu let's go down here into entities and we can open up the entities hierarchy window so here it is this one is very much like the normal hierarchy except instead of showing game objects it shows entities it also has multiple modes like the inspector and it has a toggle to see various Worlds at the same time now sometimes this window gets a little bit bugged sometimes it doesn't update if that's the case you can just reselect the world everything should update but anyways the main point is that if we look in the game object hierarchy with the subscene being unloaded being closed this way we cannot inspect the object however inside of the enti Hier key over here even though the subscene is closed we can indeed inspect the entities that are inside of that subscene now we still cannot modify it because again it was baked into binary data but if we head on play if we start playing the game again here's the bug here let's switch it into runtime mode and again here's the bug it's not updating so let's select the default world and there you go now it does update and now we can select for example this sub scene and again another strange bug on the inspector let's go back into authoring mode and go into runtime mode and in the inspector let's just go into runtime mode and yep here we do see the dots components so the ENT is alive and since the game is running now we can indeed modify this data and yep everything moves correctly whereas on the main hierarchy over here we still see just the normal game objects whereas if we stop playing and now let's open up this sub scene for editing and yep we can now see the cube and we can now start playing and yep now we do see the cube still selected in there and while the subscene is open we can actually modify it so if we go in the inspector we swap it back into authoring mode and we modify this one and yep modifying this over here on the game object inspector modifying this one does automatically trigger a sort of bake and actually modifies the entity that is currently running now when making the final build of your game you want everything to be running as fast as possible so in that case you want to close the subscenes or if you're working with tons of them you probably only want to open one of them but while building our game we're mostly going to leave it open just so we can easily add things and this en Hier window this is also very useful at some points so let's leave it open let's just put it right next to the hierarchy just like this so we can access both them easily also Note One Thing how when we head on play over here on the enti hierarchy we can see all of these entities were created some of these are default entities that Unity creates automatically to set up the entire game world so some of these are going to be related to rendering others for various systems and so on every system also has a corresponding entity but don't worry about that for now we're going to learn about systems in a little bit now let's see also one very interesting thing so if we go inside the Hier so the normal game object hierarchy and let's right click on the sub scene let's create an object inside the subscene in this case let's create a completely empty game object so if there it is a game object it's completely empty the only thing it has is just the default transform component just because this one we cannot remove so this is a completely empty G object so we can see it over here inside of our subscene but if you go inside the NT key and nope it is not in there even if you refresh this nope it does not show up and same thing if we select this game object and on the inspector if we swap from authoring mode where it does show if we go into runtime mode nope it does not show it says this is an invalid entity this is another very important thing basically the baking process will indeed convert all the game objects inside the subscene into a dots entity it will do that but only if there's anything to actually convert now in this case this game object is completely empty and when something is completely empty the baking system is smart enough to not waste any time converting that object so just be aware if you make something completely empty and it is not a child or a parent of any other object if it has no components nothing if so then something completely empty will not automatically be converted into an entity until you finally add some components which does trigger the baking process as long as you have any kind of bakeable component this game object will indeed be converted into an entity and by default like we saw dots already works with a bunch of the built-in components so if you set up your game objects with some of these basic components if so they will automatically be converted into dots components like we saw over here with the rendering the rendering did convert automatically we can look here in the runtime components we can see it has a chunk where render bounds we can see it has the material mesh info and a bunch more rendering compon components same thing for the physics we can see it as a physics World index a Col Lether and so on let's see how dots physics already works by default so let's first of all get rid of both these let's right click create a new game object and this time let's make it a sphere let's lift it up by a little bit and over there let's go into the authoring component and let's make it a little bit bigger okay there you go we have our sphere right there down here on the baking preview we can already see all the various physics components that will be based so we've got the physics leather and so on now let's add a rigid body again a normal rigid body component so a perfectly standard game object component let's add the origin body and now let's make another object so inside the subscene let's create a new 3D object this time let's make it a plane let's lift it up by a little bit and let's make it slightly tilted just so the sphere falls down a little bit okay that's really it so we created both a sphere and a plane and importantly we create both those using normal game object components the normal game object process so far we didn't do anything that was specific to dots and just with this if now we head on play and way we can see it does work we can see that sphere fell down and it's now rolling along exactly according to physics all right awesome so just like this our dots entities already have physics and everything working so this is really how awesome the baking system is we just work with normal game object components like we're used to and then they are automatically converted into entities with dots components and everything works with dots physics also right now you might have noticed something interesting so if we had on play we can see here in the game view the sphere did fall down and is now rolling down but over here on the the scene view if you look you can see on the scene view the sphere is actually still up here and if I try to move this object you can see the actual dots entity that one kind of teleports up there this is a little bit strange but it's actually very much intentional like I said the baking process happens just once you edit things and then game object get baked into binary data for all the entities and over here on scene view basically we are seeing the edit time pre-bake world and this is actually a setting that we can change so let's stop playing let's go into edit go into preferences then here on the left side let's go into entities and here we have the setting for the scene View mode here we can change do we want to see on the scene view do we want to see the authoring data or the runtime data now for the most part I find it a little bit confusing to see authoring data I think runtime data makes more sense in most cases so I usually set it on this one let's click and now if we h on play and if now we do see both in scene View and game view everything looks exactly the same all right so here we learn how dots baking works this is a really crucial part of dots it's how we can keep working with game objects for building our game but then automatically convert them into super fast entities for our runtime so now that we know how baking works it's time to create our custom component so let's do that in the next lecture hello and welcome I'm your Cod Maki in this lecture we're going to set up our unit and learn how to create a custom dos component along with its authoring component okay so in the previous lecture we already learned how the baking process works so here we have a sphere in a plane we set it up using normal game object components which are then converted into dots components so if I H on on play Then yep all these regular game object components converted into dots components and using do physics everything falls down great now that we've tested that let's get rid of these two objects and let's set up our normal unit object and for this I'm going to build the unit like I normally do meaning normally I like to have a parent game object with all of the logic components and then child game objects for other individual things like for example the visual mesh the visual selected any kind of thing like that those will be child objects but the parent one will be an empty game object with just logic so let's go ahead right click again directly on the subscenes we're trying to make an game object that will eventually be converted into an entity let's construct a brand new empty game object let's name this just a unit and if this is going to be the parent game object this where we're going to place all of the anic components and now inside it let's make another empty game object so inside let's create another empty one call this one the mesh let's make sure that it's on 0 scale LEL 111 okay great now let's add the usual visuals so the mesh filter and the mesh render component and for the mesh let's select over here the soldier aim mesh so y there it is the soldier aim mesh and for the material let's make sure to assign the one over here inside materials characters the soldier material like this and if there this there's our nice mesh visual so we have our soldier unit now I like the structure of having an empty game object and then children for individual Parts personally I find that it really helps me stay organized and becomes quite a bit more versatile as we want to add more things onto the unit like one common example is sometimes you have visual meshes that are not exactly the same size that you want and if you take this approach then you can easily scale you can modify put it on some kind of Offset you can apply that on the child object and leave the parent object on the exact same position with scale of 111 so that's one of the many benefits of this method let's go ahead and reset this to everything on zero and 111 and like I said later on we're going to create more objects more CH objects those are going to be for the selected visual the fog of War shape the mini map icon and so on all of those are going to be Chun objects so so this is how I like to set up my objects when Parent Game objects with all the logic then visuals and other parts in child objects but just to be clear this is not a requirement like we saw we can create just a regular sphere and use everything directly on just one game object so I just want to clarify what is a personal preference versus what is the requirement so anyways here we have our game object set up and it's already correctly being converted into an entity if we hit on play and we see on the entity's hierarchy yep here we have the mesh entity again the parent is not being converted because right now it is is actually empty like I mentioned in the previous lecture a game object will only be converted onto an entity if it needs to meaning needs to have some kind of component that will be baked in order for the entity to actually bake so now is a great time to see how do we create our own custom dots components now this is actually going to be pretty simple so over here on the project files first of all let's create a nice folder to organize all of our scripts so right click on the assets let's create a new folder called scripts and now inside let's right click on the scripts folder go under create and now here we've got tons of menus so let's go go over here inside the entity submenu in this case we want to create a component so let's choose an i component datas script let's name it move speed like this yep that's it let's open it and here it is here we have a component it is super simple as you can see this is all it takes to define a component you just need to implement I component data this is an interface but this has no methods you need to implement it basically just works kind of like a tag to identify this type as being a component by the way this interface itself as you can see exists inside the unity. entities name space so make sure you add the using statement up top and the other very crucial part is this has to be a struct this is extremely important and it's why dots is as fast as it is remember what we learned in the what is Doc lecture how the insane performance benefits we get from dots comes from being basically very clever about memory usage now normally in C code you work with a lot with classes for example mono behaviors those are classes and the main difference between class and structs is how classes are reference types whereas structs are value types or another way that un likes to refer to those two types is as either managed or unmanaged meaning their memory is going to be either managed or unmanaged by the C runtime so classes are managed components or reference types whereas structs are unmanaged components or value types other examples of Val types are the basic types like in float bowl and so on and reference types are classes and pretty much any kind of object so for example arrays are also reference types and strings are also reference types now the difference is for example when we define a class and then we we construct an object of that class when we do that like I said classes are reference types meaning this variable over here this one is not storing the class object directly it is not storing the actual class data Instead This variable really just has a pointer and then that pointer points to a certain position in memory and this memory itself this memory position this is what actually contains the class data whereas if we Define something as a struct we can struct a brandy struct and by doing that that struct that variable is actually holding the actual struct data there are no pointers there are no references to anything the struct data is stored directly here the power of dots is really all about how it handles memory how it packs memory in some super tight chunks and doing so then allows the code to run super fast between all the components within this chunk it is super fast because it is accessing contiguous memory locations meaning one all after the other whereas with game objects those are regular objects so for those the CPU basically has to jump from all kinds of positions in memory in order to find whatever kind of data it needs so it needs to go forwards backwards and so on constantly jumping in memory and this is actually quite costly this leads to a lot of things called Cash misses which is where the CPU basically loads a ton of positions in memory when it requests one position which is how the CPU basically requests a ton of positions in memory and stores it in a super fast cache but then if you need to access some other position that is not loaded within the cache then basally needs to unload that entire cach load the new cach and finally grab that memory so that is how when dealing with ECS when the CPU loads an entire memory chunk into the cache since all of the memory positions are contiguous all of them get access without any cache misses that is how dots is so insanely fast so when working with dots almost everything is going to be based on structs in order to benefit from that memory management now in general changing something from a class onto a struct literally just means swapping out the keyword instead of class we write struct and yep that's it that defines it as a struct and in doing so naturally we change it from reference type onto a value type however that change does have some very important implications the main one being in terms of working as something as a copy versus as a reference so for example if we have a class my class and we construct an instance of that class and then a second one and we make it equal to the first one when doing so both these variables my class A and my Class B both of these are storing the exact same position in memory because again these are classes meaning they are just storing the positions in memory they are not actually storing any data itself and in doing this basically they are both just storing the exact same position memory and the external data they are both pointing to the exact same data now what that means is if we went to go through my Class B and modify some field inside of it it would also modify the value inside my Class B because again both variables both are referencing the exact same underlying data whereas if we do that with structs structs are valid types and not reference types so if we do the same thing so construct a brand new struct and then assign a second one onto that one if we do this instead of having two variables that both point to the exact same object instead of that we have two copies of the underlying data so if we were to modify some field inside myru B it would not automatically modify anything inside of myru a because again both are separate pieces of data they are not pointing to the exact same thing when working with structs and when we assign a struct what we are doing is we are creating a copy we are not storing the same reference to the original data in memory we create a copy of the data so when we modify something inside myru B we are modifying just that copy and we are not touching the original data at all now this is really very crucial to understand you must fully internalize this difference really understand how structs work as copies and not references you need to know this so that you don't get confused when at some point you write some code and have no idea why it isn't changing it is probably because you're working with a copy of the data and not the original data itself for example later on this course when we write some systems we are going to see how if you get some component and you just modify it it won't actually update the value in the component attached to the end because again the component will be a struct and structs receive copies so modifying that copy will not modify the original data but we'll cover that when we get to systems for now I hope you understood the difference between structs and classes the difference between value types and reference types or the difference between managed and unmanaged all of that is extremely important to dots so now we can continue working with our components all we need to define a component is again make it a struct and make it Implement I component data that's it this is now a dots component and now inside this we can place whatever that we want to store inside of this component for example for some kind of move speed component let's just sry float for the move speed value so we literally do just this so public float and call it value that's it also by the way if you're a regular on my channel you might have heard me talk a lot about clean coat principles and the main one is how you should never make everything public usually I tell you to always make it private and then expose it with some kind of field like float get value and over here you would return the value this gives you a lot more control as to how your fields are accessed so that's how I usually recommend you do it however ECS is a very different thing that oriented design is very different from object oriented programming for example components in ECS these are not meant to have any functions at all these are just meant to store data just Fields just data so you are really not supposed to have any kind of functions inside of your component technically you can do it the compiler won't stop you but you really should not put any functions inside of your components the general idea of ECS is you have entities which are really just IDs then you have components and those should only store data and nothing else and then you have systems which are the things that actually do some work do some Logic on that data so since that components are really just meant to be simple data containers if so then makes sense for them to just have their data directly exposed so making it public this makes sense in dots World in ECS world when working with normal game objects I definitely encourage you to keep those same clean code principles in mind when working with Mod behaviors always minimize access as much as possible but over here in the world of Dos in the world of ECS go ahead and expose your Fields by making them directly public okay so here we have defined our component the component is called move speed and inside we just have a value field of a float so let's just go ahead and save this and wait for Unity to compile however now if we inspect our entity if over here we click on the unit and look at the runtime component and nope it still does not exist The Entity does not exist because again it's completely empty so this entity would not have any component naturally it did not magically get our newly created component added so the question is how do we add a component onto an entity so one way is through code we can just call a function to add a component onto an entity we're going to do that later on many times but once again we can really just use the baking process so like we already saw for the default components how those get used as normal game object components and then that get converted get baked into dots components that is all the baking logic and we can also Implement baking Logic for our own custom components that way we can keep building our objects using normal game object components and then have them be baked into dots components so way we do that is with a mono Behavior component so on these scripts let's right click go ahead and create let's create a new mono Behavior script and now for the name a nice convention is to name it just like the components so move speed and then simply append the word authoring onto it so move speed authoring so yep just like this here is the normal monob behavior component the standard thing that I'm sure you're very used to now here we can add whatever fields we want to have in our mon Behavior component in this case since in our move speed component in this one we expose some kind of value let's do the exact same thing so over here on this one let's also expose a public float value however again let me mention this is not a requirement like we saw in the previous lecture you can have one authoring component that gets baked into multiple different dots components so your components do not have to have the exact same field it all depends on what you're trying to do in this case we do want to easily Define the move speed value in the authoring component and use the exact same thing in the dots component sa here on the mon behavioral let's find find the same public float value okay let's go ahead and save this wait for un to compile then let's select our unit and in the inspector let's put it back into authoring mode and let's just drag our move speed authoring component so just the same as any authoring component however just like this we still don't have any baking we can see down here the empti baking preview that one is still empty we have created a dots component and we have created a mono Behavior authoring component but those two are still completely separate things there is no connection the way we Define that connection or rather the way that we Define the baking logic is with a baking class so here inside of our mon Behavior inside let's define a nested class let's make a public class now we can name it whatever we want I like to name it just Baker and then the very important part is let's extend and let's extend the baker class and this one right here the one inside the unity. enti namespace so make sure you add that one on top and this one takes in generics and the generic type should be what type we want to bake which in this case we want to bake this type the move speed authoring so let's go ahead and put it like this so yep here we have a baker class which extends this Baker class now the important thing is over here on the type that you use inside the baker generic it is the authoring class it is not the dots component it is not this one it is the authoring component okay great and also like I said for the name you can call it whatever you want you can use whatever word you want here it doesn't really matter it does not have to be called Baker but I think that makes quite a bit of sense and also technically it does not have to be an N class we can put it down here and everything works the same but again I think it makes sense since it is related directly to this component it makes sense to place it directly in here so with this we have defined our Baker and we can see we have an error basically we need to implement this bake method so let's do that and actually we can use Visual Studio to help us we can place the cursor on top of the error then use the quick action to implement the abstract class and if there you go it writes the code automatically if you're not using visual studio or you don't have these kind of quick actions you can just manually write this function so we've got a public override void we're going to override the bake function and this one is going to take in a parameter of the exact same type as our authoring component okay so now we need to implement this function now this function this one is going to run during the baking process and in this function we do have an access to our authoring object meaning this is where you can grab this component which in itself has all the data that we want to expose and we can convert this into our regular dots component and in order to add our dots component we use the add component function and this one takes in an entity parameter so the way we get our baked entity is with another function so let's call get entity this one one takes in a parameter for our transform usage Flags now this is a really nice optimization thing it has to do with whether we want the baked entity to have a transform component or not like we saw a while ago if we were to remove the Box component then the baked entity would not have a local transform component that's an optimization thing so here for the transform usage Flags we have a bunch of options for example if our entity never moves and does not have any kind of concept of a worm position like for example let's say if it's an inventory container if so then we can just select none and it will not have any dots transform components or if the entity does have a worm position but will never move like for example static visual objects placed in the world for that one we can use renderable in doing so it will have a matrix component in order to be able to render but will not have a local transform since again it will never move so if you want maximum performance definitely choose the most restrictive usage Flags you have here but in most cases you probably want your object to be able to move so in this case let's go ahead and choose Dynamic this means this entity which in this case is going to be our unit this one will have all the transform components which means it can have a worm position it can move rotate scale and so on so y this function will now return our baked entity and now using that entity we can then add some components and specifically in this case we want to add our move speed components over here just new move speed and let's add this component yeah that's it we are adding it but we also want to assign the value in there so instead of adding it like this instead of constructing using the parameterless Constructor instead let's just open in C the curly braces and then in here we can set the value so this is the value inside of move speed we can grab the value from the authoring component so let's go inside the authoring component and grab the same value okay so yep that's really it so basically this function is going to run during the bake process in doing so it will create an entity that has the dots transform components and then it will add a component onto that entity and the component we're going to add is our custom move speed component and that component will be initialized with the value field on exactly the same as we have in our authoring value field so that's it let's save just wait for it to compile and now here in the editor let's make sure the inspector is on authoring mode and over here let's set the value speed again on the authoring component so the mono Behavior component let's set it to some number like let's say 56 and yep now let's go swap the inspector into runtime mode and sometimes this bug happens so this en does exist but for some reason this bug happens if it happens very simple just deselect and reselect the unit and Y there you go now it does show and if we scroll down here yep we do see it does have our custom do moveth speed component and yep the value does match exactly the one that we set in the mono Behavior component all right awesome so basally we created a brand new component type called move speed it implements I component data meaning this is a dots component then we also create an authoring component this is a normal mon Behavior component we attach that normal mon Behavior component onto our normal game object then we wrote the bake logic in order to convert the authoring component into a dots component and if the final result is that our B baked entity does have our custom dots component with exactly the data that we want so yep everything worked perfectly now that everything is working let's just do one more thing so right now we have two scripts the move speed and the move speed authoring this works as you can see but in order to not end up with literally hundreds of fils in our project with a ton of duplication in order to not have that we can also just merge both these into just one script to do that let's go ahead and grab our dots components so let me cut this one go onto the authoring component and let's paste it right down here now let's go ahead and save both these files and unity wait for it to compile and let's delete the move speed okay up like this let's make sure everything s works and yep the unit does still have the dots component and on the authoring yep does have the authoring component so this works but now we have just one file and this one file contains both the authoring component the baker logic and the dots component so this makes it quite a bit easier to work with everything is just in one place very easy to work with also let me make just one quick note here in order to make this work then the name of the file here the file name itself this one has to be named just like the monob behavior component if you were to name this file just move speed it will not work in order to use this authoring component as a regular actual mon Behavior component in order to use that and be able to attach to some kind of unit then the file name does need to match whatever class is inside of it so in order to use this method of putting everything in just one file just make sure the file name itself does match the authoring component so y down here we have our dots component then we have the authoring component and inside we have the nested Baker class which bakes our authoring component onto our dots component this is the standard format that I'll be following throughout this course when making components dots component authoring component Baker class and so on Also let's keep our project nice and organized we're going to end up with tons of scripts that's one thing about dots you do end up with quite a lot more files than with object-oriented programming so in order to make sure this does not become very messy let's make things nice and organized so inside the scripts folder let's right click let's create a brand new folder and call it authoring and this is going to be where we place all our authoring components let's just verify again that everything is working let's set on play mode Let's select the unit yep it does have the component with whatever value we want then go into runtime any y it does have the move speed component the dots component okay great all right so by now we have already learned how to create entities by placing game object inside a subscene and letting the baking process do its thing we also learned how to create a custom dots component and how to create the authoring component that bakes game object data into dots data so we've already learned both the E and C in ECS the entities and components now what's left is the s for systems so let's learn about that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to write our first system to make our unit move this requires us to learn how to do entty queries we're going to first just move a transform and then later on do it using physics okay so far we have our move speed component it stores a field for the actual value that we're going to move we have implement the baking system and attach the authoring component to the game object so the final entity is going to be baked with our component and with the correct value but so far it's not doing anything if I head on play then obviously nothing happens so going back to how ECS Works entities are just IDs components store data and systems are what the logic on that data so let's make a system to move our unit so here in Project files again let's keep things nice and organized so inside the scripts folder let's make another sub folder this going to be for our systems and now inside the systems folder right click let's go into create let's go down under entities and now let's make this one an i system for the name let's call it unit mover system and let's open by the way personally as a rule I like to append system to the name of my systems you don't have to it's not a requirement I just find it helpful to easily be able to identify what types are systems okay so here we have our default system now once again dots has some very specific requirements so first of all we need to implement I system this interface has a bunch of functions this one also needs to be marked as a struct not a class and importantly this one needs to be marked as partial now if you're not familiar with the partial keyword basically this is how you can define a type in multiple files so you can Define part of the class or the struct in one file and then another file Define another part the way dots works is very much based on Source generation meaning you write some code but then the system autog generates a ton more code in the background to make everything work that's how despite dots actually being so complex it is not that difficult to use it is because a lot of the tricky code is actually autogenerated but here the important thing is these requirements Implement I system make it struct and make it partial also let me make one quick mention ECS actually has two different system types we have our I system but then there's also system base now difference between these two is system base meant for managed systems and I system is meant for unmanaged or put in another way is system is meant for structs and system base is a class now in general you should prefer I system as much as possible basically because it won't be bur compatible and much much faster in this course I actually don't think we're ever going to be using system base just because whenever we want to do something that use lots of manage data we're actually just going to make it using a normal mono Behavior so in general don't really worry too much about system base just know that it exists but for the most part we're going to be using I system okay so here we have our system and as you can see we have our three function by default on create on update and on Destroy so their names are pretty self-explanatory on create is going to run just once when the system is created then on update this one is going to run on every single update pretty much like a regular monob Behavior update and finally on Destroy This one is going to run when the system is destroyed now in terms of life cycle for systems by default systems will automatically be created and destroyed so you don't actually need to worry about manually doing this as soon as we play the game the automatic bootstrapper will handle all that it will automatically create all the systems and handle all that logic so we don't have to manually initialize it in any way we don't need to add it to any entity any object just by existing just by implementing I system it will automatically be registered with the automatic boot Sy and these functions are also optional so for example to keep things simple let's actually delete the oncreate and the on Destroy since we're actually not going to be needing these right now right now all we want is the basic on update also you might notice the burst compile attribute over here going to talk about burst in a little more detail in a future lecture when we work on the job system but basically by adding this attribute over here by doing this we are enabling burst compil directly on this function meaning it's going to use burst which can make it super fast again this becomes very important later on and I'm going to cover it in a few lectures but for now just leave it on just like this now the goal with this system our goal is to move our unit so if we go back to the theory behind dots the reason why it is so fast is because of memory management how it packs memory tightly together for all the components that way makes it super simple to use cycle through thousands of components and the way we're going to run our system logic is with a querying meaning we Define all the components that we want to run that query and then the code will automatically cycle through all the entities that match all of those components here in the code the way we Define a query is pretty simple we just use system api. query this one takes in generics and the generic parameters over here is going to be where we Define all the component types that we want to query for so in this case we want to move our units so to move them we're going to need the transform so the dots transform which is actually called local transform and this one exists inside unity. transforms and just with this we should be able to to move them so this is our query and this function over here this one returns an inumerable meaning the way we cycle through all the entities that match this query is by putting this code inside a 4 each so let's do a 4 each and for the parameter it is going to be of the type of the components that we're grabbing so local transform call it local transform in our query and yeah just like this now any code that we write inside of here all of this is going to run for every single entity that matches this query however it's not actually like this this code will not actually run properly once again it's due to how structs work they are value types meaning they work as copies so if we just use this code and we modified something inside this local transform variable if we did we would only be modifying the local copy and not the original data in memory so the unit wouldn't really move so because of that over here in our query we never write just the component type directly instead we have a helper class that essentially kind of transforms the stru into some kind of reference type so that type is called refr and this one takes in a generic for the actual type that we want to cycle through so you have to put refr W in there in the query and also over here on the iterator Y just like this so ref really just means this going to act as a reference even though again even though the underlying component this one is a struct by using this one we are essentially turning that struct into a reference so as we modify things inside of this variable we're actually going to modify the actual data and then RW that really just stands for read write meaning we can read this component or we can write to it it and the other alternative is we have ref R this one stands for read only meaning with this one we can only read from this we cannot write to it so now you might be asking why would you ever limit yourself to read only if you can read and write and the answer is this will actually become super important later on when we work with the job system meaning when we have code that runs in parallel on multiple threads I will explain more when we get there but the general idea is you can only write to something from a single thread whereas you can read that concurrent ly from multiple threads so for example if we have aund entities and we're running some job that reads thata on all those entities then we can have for example 10 threads all reading data at the exact same time whereas if we are using a refr W for read and write if so in that case then all those entities could only be processed in a single thread because you cannot have multiple threads right to the same data at the same time so in general you should only request the level of access that you absolutely need basically the more ref Ros you have the better the more refos you have the more parallelized your code will be so if you only need to read something definitely make it a refl but if you need to read and write then go ahead and make it ref R dou in this case we are trying to make the unit move meaning we're actually going to need to write a brand new position so because of that let's go ahead and use ref RW okay so yep here we have our nice system with our query and now like I said the code inside of this for each this will run for every single entity in our world that has a local transform component and just quickly let me make one more note on multi-threading right now this code is not multi-thread at all this for each will just run on the main thread no matter how many entities we have so if we have a th000 entities then this for each will run through all of those thousand entities on the main thread one by one making something in I system and writing a 4 in that by itself does not make it multi-thread by default we're only going to make this code multi-threaded when we Implement jobs in a few lectures so I just want to very quickly point that out okay so here we have our 4 in now like I said this will cycle through all the entities that have a local trans component and now inside of here we can do whatever we want to this local transform so as a quick test let's just move everything to the right so let's access the local transform and now inside we have two nice properties we have the value R and the value RW again same thing read only or read WR in this case we want to write to the position so let's grab the RW and we're going to write onto the position so let's modify this field let's put the position equals and they going to move right so let's grab the current position so local transform right now we just want to read so let's grab the value R to grab the current position and now we want to move it on to the right so let's just add a new flow three onto it and by the way FL three this is a special type that is part of the unity. mathematics Library so let's go up here at using unity. mathematics and over here we can define a new FL three this mathematics library is what I mentioned a while ago on how it's super fast and specifically designed for dots and burst so this float three over here this one is basically a vector 3 meaning inside we have floats for x y and z so really just like effector 3 so in order to move it on to the right for this let's construct a brand new float let's put it one on the X to move right zero on the Y and zero on the Zed and yep so we add this onto our position and we save the brand new position so just like this this will move to the right by one unit except as I'm sure you know when moving anything you want the movement to be frame rate independent so over here let's make sure to multiply by time. Delta time however again dots also has a special time. Delta time we should not use the default one this one for the standard Unity engine we want the one that exists in the dots world not the game object world so instead of time. time we go through the system API go through this class access time and finally Delta time so yep just like this okay so here are code is done so we have a 4 in doing a query on everything that has a local transform and this code inside of here is going to run on every single entity that has a local transform component it is going to grab that one and set it to basically the same thing moving right by one unit okay so let's go ahead and save and let's test so hit on play any your PR wait does work there's the unit constantly moving right all right awesome except it's actually not entirely awesome so this is working our unit is moving but it's actually not just our unit as test over here on the hierarchy let's go inside the subscene and let's construct a brand new let's say Cube let's create a cube and let's put it over there okay so we have our unit and we have a cube and now if we hit on play and you have look at that both the unit and the cube both of them are moving right and not only that but actually the child mesh object that one is also moving right that is why the unit seems to be moving at Double the speed as that one so basically everything is moving right now this is actually a key point about dots it's how systems do not care what a certain entity represents the system does not care does not know that this is a unit and this is a cube it does not know any of that if an entity has components that match the query then the system will run Logic on that entity so basically how you define whether something is a unit or a rock or something like that the way you define that is by adding components onto it by the way there's also a systems entities window so if we go up here on the menu let's go into window down into entities and open up the systems window and Y this one over here is going to show all the systems that run all the time so let's go ahead and head on play in order to see these in action so let's head on play and now if we find yep here is our unit mover system and over here under nty count we can see three meaning our system is being applied to three entities so that's the cube that's the parent game object that's the parent entity and the child entity with visual mesh so naturally this isn't what we want we want to just apply the movement onto the unit so over here this should be saying one this systems window is sometimes useful so let's leave it open let's just put it over here next to the console okay great so now let's figure out how to make our movement apply just to The Entity that we want in this case that's actually going to be super simple we can just add another component to our query that only exists on the unit so we can just use the move speed component that we already created this one only exists on the unit and only on the unit parent object so that one should perfectly Target just the unit over here in the code let's add some more components over here into our query and the way we do is very simple just add a comma and then another type this case we want the move speed component again importantly it's a move speed not the move speed authoring nope over here we're working in the dots world so we want the dots component and again we need to Define either refr W or refl in this case we only want to read the speed from it so let's use ref rro just for reading so we add it over here and then also need to add it over here on the first parameters and when we have more than one we need to put this inside parentheses so let's open parentheses over here close them over there then do a comma and add the move speed component also for readability I like to add some new lines so add new line for every single component then new line over here on the end and then on the query components and Y just like this it is nice and readable so we are doing a query with local transform and move speed and importantly is this is an and operation meaning our query over here it is going to be looking for entities that have both of these components they need to have a local transform and a move site component in order to run this code but at the same time it is not an exact match meaning it can have more components than just these two it just needs to have at least both of these also after the query after we open and close the parenthesis afterwards we can add a bunch more options we can type with and we can see all kinds of things for example we can use with none in order to specify this should only run on entities that do not have the falling components we can use with disable this will make it included include enable components that are disabled and so on as you can see we have tons of options we're going to use these a bunch later on to make some more complex queries but for now let's keep it simple we just want these two components local transform and move speed since our unit is the only thing that has both these then this should only run on the unit also one quick note in terms of syntax so you can write code like this this is personally what I prefer to be very explicit with exactly everything single type however if you like if you prefer you can also just use VAR so just type in VAR before that par and then over here do not Define the type just Define the names just like this and Yep this is valid code this is valid syntax this works exactly the same Some people prefer this Unity actually uses VAR a lot in their own documentation now personally I am not a fan of VAR I like my code to be as explicit as possible so there are no questions I want to be very very clear on what type my variables are but again that's really just a personal preference kind of thing so if you do like VAR then you can definitely write your code just like this but I won't be sticking with my preferred method of being more explicit by defining all the types exactly okay so far so good so we have our query and the query is going to run on entities that have both of these components now let's just use the move speed value directly in our logic so instead of moving right by one unit instead of that let's read the value so let's go inside the move speed go inside the value Arrow because we only want to read it and let's grab the value field inside of it so yep just like this let's go ahead and save and back here in unity let's modify the authoring component and make it can move at a speed of maybe five okay now let's hit on play C and Y there it is now our system is only applying to that unit it is not applying to the cube it is not applying to the Chann MH anything now it is only running exactly on the thing that we want so it is only running on the entity that has both a local transform and a move speed component by the way we can also edit this value in real time so over here I can click and drag to modify it and yep it does work and also if we're in the other inspector so let's go in runtime mode so here is all of the components move speed and I can also play with this and yep all the changes work now this is another example of dots data oriented design and action we can very easily modify the data and then by doing that when these systems run Logic on this data it will then have a different behavior all right great so here our unit does move towards the target we've achieved Movement by directly moving the transform but to make the game feel a little bit more interesting we're actually going to want to use physics in order to move this unit so let's add that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to move our unit using physics this is going to be quite easy actually thanks to how Unity handles the built-in physics components by default okay so here's what we have so far the unit is constantly moving so it has a component for the move speed it has a system called the unit mover system and it is moving the unit so that's it very simple except right now it is only moving by moving the transform directly we want the unit to be able to interact with other objects so let's make it using physics but before we Implement physics let's just add one tiny thing so over here right now the unit is moving but it looks a bit odd as it's facing forward and moving left so let's make it rotate towards the move Direction so here we are in our unit mover system okay we have the local transform our move speed component okay great so in order to rotate towards that direction first of all let's actually calculate the move Direction Vector so we have a float for a move Direction Vector actually this is a float three which again is pretty much the equivalent of a vector 3 it's just in the special mathematics Library so that one first of all requires the target position so let's actually Define it as opposed to over here we're just moving right or actually just moving towards the move speed so let's define a Flo three for the Target position this target Position will eventually be an actual proper position like for example the mouse position or whatever position we tell this unit to go to but for now again let's just make it move to the right so Target position just go into the local transform onto the value r o just for reading let's grab the position and add a new FL three and just go to the right by 10 units okay so this is our Target position and in Direction some super simple math so just Target minus the current position so that's the local transform do value Ro for reading and let's grab the current position so this calculates our move Direction Vector except again as I'm sure you know when it comes to Vector math over here this Vector will not be normalized so let's make sure to normalize it to set the magnitude to just one when working with the normal Vector 3 usually you can just call do normalize but over here this one does not have that so normalizing a vector in the new mathematics library for that one you assign the vector go inside the math class again this is the one inside unity. mathematics inside of this one there is a normalized function so this one takes in a parameter so we pass in our move Direction and it Returns the move Direction but normalized okay so yep so with this we have our move Direction and then let's just use it over here so instead of recalculating the direction as well let's just set the position and let's do position plus equals let's add on to the position let's move towards the move Direction multiplied by the move speed let's grab the value R for reading and let's grab the move speed value and then finally the time. time okay so yep just like this we should be doing the exact same thing so really just moving right let's just quickly verify in order to actually make it move right let's make sure that the move speed component does have a positive value otherwise if it has a negative speed then naturally it's going to move to the left side so let's select our entity inside our subscene and let's go into our authoring component over here just make sure that some like three okay let's test and if there it is unit moving right okay great now let's add the rotation so adding the rotation when we have move Direction This is actually surprisingly simple on the local transform that we've been using on there we have the position but then we also have a rotation we have a rotation as well as a bunch of functions to rotate by a certain amount in this case we want to set the rotation to something now in this case this rotation field this one is a Quan and again note how it's quion written like this it's on lower case not uppercase this is the mathematics Quan so to get a quan for this move Direction it's actually surprisingly simple we can go inside the Quan class and then we can use the function L rotation this one takes a forward rotation so let's pass in our movement Direction and then an up Vector so here we can just do new flow 3 0 1 0 so this is our move vector or we can actually use a constant and the constant is going to be the math. up and this is actually a function this will return the exact same thing 0 1 Z and yep like this it should work okay so with this let's do a quick test also one thing definitely make sure that you have the chall object definitely make sure this one is EXA like this everything on zero it should be on position 0 0 0 rotation 0 0 0 if you do like this it should point in the right direction but if you apply some kind of rotation here then it won't point exactly so make sure all of these are on zero and let's it on play and Y it does work look at that there's our unit moving right and facing right all right awesome okay so now we have achieved our Movement by just moving the transform but to make the game a little bit more fun we want to use physics we want our characters to be able to interact with other physics objects so let's do exactly that as usual let's set up our unit over here with normal components so let's select the Parent Game object and this one over here let's give the unit to shape so let's give it a regular capsule collider then let's set up the settings we can see over here on the scene view so let's make it a little bit higher so with a height of two for the radius .5 yep that looks good and let's just lift it up a little bit so it doesn't touch the FL let's say 1.1 okay yep so there's our unit collor and again just like this just by attaching a caps collor just this will automatically convert into dots physics we can already see down here yep the unity. physics. physical this one will be add so with this we have a collider and then for actually using physics we also need a rigid body so let's add that one a rigid body and again just by adding it add a bunch of bait components down here then for the ridge body settings over here for the interpolate we want it to be nice and smooth so let's make it interpolate then we don't want this unit to fall down so let's make sure to disable gravity and over here on the constraints our unit should really only move on the X Z axis so let's freeze them on y we don't want them to move up or down and same thing for the rotation since we're going to rotate them manually okay great so that's our setup again using normal game object components and if we put the inspector over there into runtime mode and up here we do see all of the various components now our goal like I said is to move this unit using physics meaning for move it we actually want to modify the velocity and yep we can see it right here this is the component we want to modify the physics velocity this one has a linear for the linear velocity and angular that affects rotation so instead of manually moving transform we want to be able to set this linear field directly inside the physics velocity so back in code here in order to be able to modify the component we just need to add it over here in our query so let's add another one in this case we want to modify it so let's make it a ref RW and call it the physics velocity and yep it is this one again inside unity. physics let's make sure to add this name space so Yep this is the component that we want and let's also add it up here so you've got the refr physics velocity physics velocity okay yep so we added a new component to our query and now down here for the rotation we still handle it normally but for the movement instead of moving the transform directly instead of that let's go inside of this one let's go inside value r w because we want to write to it and we're going to modify that linear field and linear velocity this one is going to be set to our move Direction multiplied by our move speed so move speed let's grab it just for reading and let's grab the value and yep that's it again here make sure to not include time. Delta time here this is really just setting velocity is not actually moving the object then the physics system afterwards they will't apply the time. Delta time or actually the fix Delta time and that is what actually moves the object so make sure you don't included over here and also since our units are going to collide with each other that's actually going to mess things up and actually trigger some rotation later on we're going to implement some proper collision avoidance logic but for now while that is still going to have tons of collisions we don't want it to completely break everything so let's make them not rotate so here let's make sure even though we freeze the rotation even with that it will still rotate if it forces some collisions so let's manually just set the angle velocity into zero so we can just go inside flow 3 and access flow 3.0 okay yep just like this should work so instead of modifying the local transform position instead of that we are just assigning a velocity so let's save and now let's test any if there this unit is still moving exactly as intended except now it is doing so using physics now we can actually verify that so in our scene let's set some objects so inside the nty subscene I'm going to add a bunch of Cubes so let's construct a brand new Cube by the way you don't need to follow this part this is really just for testing just make sure that all of this is working so I'm just going to place a bunch of Cubes place them like this one over here one over here then place a bunch more on top and a bunch more on top and for all of these let's also add a rigid body component just make sure they fall down rigid body just like this okay so with this we have a bunch of Cubes our unit is going to go right and should interact directly with those cubes so let's try and test except nope that didn't actually work the cubes fell down and fell down through the ground and actually that makes this an excellent time to mention how dots physics and game object physics those are completely separate those are two completely different worlds that do not interact with one another these cubes that we just created these are placed inside a subscene meaning these are going to be converted into entities they're going to be using dots physics but the ground this one is still a normal game object outside of the subscene meaning this one is using just normal game object physics so that is why the cubes went through the ground that is because they are working on completely different physics systems it's as if for the cubes the ground does not exist and it's as if for the ground the cubes do not exist because again both physics were like completely disconnected now in order to see this work is actually very simple let's just drag the ground directly inside the sub scene and now they should all be baked into dots physics so now let's test and okay yep they stay there the unit goes and if there you go the unit does move and does interact with those cubes all right awesome okay so here we are using dots physics the unit moves it goes through interacts with those objects and everything works great and again remember how dots physics and game object physics those are two completely separate worlds so let's revert what we did for this testing let's put the ground back outside and let's delete all of our testing cubes yep just like this okay so here we set up our unit mover system which is a query for some components that match exactly what our unit has then it used that to move that unit we saw how to do it by moving a transform directly and then by moving it using physics however right now our unit is moving to a fix point it is constantly moving to the right so let's Implement some Logic for making move towards the mouse position so let's do that in the next lecture all right quick information I just want to ask you how are you getting with dots does the concept of entities components and systems does that make sense what about the baking system are you finding it relatively easy to write code in a data oriented mindset dots is a very new technology and I tried as hard as I can to make the course have a really nice smooth learning curve so I want to hear from you if you are managing to learn everything correctly I found that during my own research once I started understanding the core concept behind dots everything suddenly became much much easier nowadays after all my research after learning a ton now I can very easily picture a new system in my head and already think about all the components and how do I organize them in order to make whatever I want to do so do let me know in the comments your thoughts so far feel free to post any questions you have and I'll do my best to help so pause the video to do that and then let's continue on to the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to get the mouse wor position so we can tell our unit to move there we're also going to learn about one very important topic which is deciding what system should be using dots and which should be normal Modo behaviors all right so let's get our Mouse R position now how to do this is actually quite simple in technical terms the more interesting part in this case is where do we write this code now when I was first researching and making the prototype for this course I started by making it a normal IE system using dots and it did work I had some logic working on a system I would store the mouse position in a component and read from it from various other systems then I added the selection Logic on top of it and again I got it all working with dots but the whole process was definitely becoming needlessly confusing and very convoluted so that's when I remembered how you don't have to build everything using dots always remember how you don't have to go 100% dots or 100% game objects you should mix them and use the right tool for the right job so the rough general rule that I came up with is actually quite simple for things that are not performance critical or simply don't run all the time or only run on a single object so things like Mouse R position or the unit selection manager or the resource manager inventory and so on for those write them as normal monab behavior scripts and then for things that do require maximum performance or impact lots of objects like for example moving units for that do use dots so that's a rough guideline that we're going to follow throughout this course following that makes things quite a bit simpler and makes it easier to decide when should something be dots or a mono Behavior so with that said let's make our normal Mouse position script we're going to make a normal script so let's go inside the script folder let's actually make another folder for the mono behaviors and let's right click inside of that one make it a normal mod Behavior script and let's call it the mouse World position then as always let's make a normal game object to run it so an empty game object with the exact same name again outside of the subscene this is a normal game object let's attach the script onto it let's reset transform put everything nice and clean and open it okay so now here let's use some super simple mouse worm position logic now there are various ways we can do this we can either use physics or not use physics so let's do the similar approach without physics first let's make a function so make it public so that everything can get this we're going to return a vector 3 and let's call it get position so this will return the mouse WR position now in here let's begin by constructing a ray from the camera so we can access camera. main this is going to be our main camera and from there we can call the function screen point to Ray this one basically takes in a screen position and converts it onto a ray object and for the screen position we can get the mouse screen position by using input. Mouse position also by the way here using input. Mouse position here we are using the input manager instead of the input system now if you're seeing some kind of error in the code here that is probably because you don't have input manager enabled although if you downloaded the exact same project files it should already be set up correctly but if not let me just show you let me just return something just so this one doesn't throw an error so just return that okay let's save so here in the editor you can go into edit then go into project settings then on the left side let's go over here onto the player tab then scroll down inside the other settings tab and if you scroll down down here we should be able to see yep the active input handling and over here you can select use the input manager or the input system or you can select to use both personally I really like using both the input system is really awesome but also quite a bit more complex whereas the input manager is super easy to use so while you can write the same logic using the input system personally I really like the input manager just for its Simplicity and of course always remember you can always refactor your code so this is actually how I normally build all my games I start off with the simplest approach possible and then later on eventually I refactor it so in order to be do that let's make sure both are enabled which again should already be done by default so back to our code here so we have this and this one is going to return a camera ray object let's actually name this mouse camera ray so it's going to be a ray that starts from the mouse position and is pointing directly as the camera is pointing so now with this we just need to know where does this Ray intersect our game plan so for that let's construct a plane like using the plane class to Def find a new plane construct a brand new plane this one takes in a normal and the origin so for normal let's use Vector 3. up we want the plane to be facing upwards and for the origin Vector 3.0 okay that's our plane and now with this we can simply do a ray cast against this plane so let's go inside the plane do a ray cast using our Mouse camera ray then this is going to return whatever distance we hit so let's return out float and just call it distance this one is also going to return a bullion whether it hits something it should always hit something but let's put it inside n then if it hits something then we can simply go inside the mouse cam array and we call call get point this one basically returns a position within along this Ray axis at a certain distance so let's just use our distance and Y this going to be the mouse World position and if it doesn't hit which should never happen it should always hit something because the camera is always going to be pointed slightly downwards but still just make sure this code compounds if not let's return Vector 3.0 okay that's it pretty simple we construct a ray object starting from the camera and using the input Mouse position that's the screen Mouse position then we construct a plane directly on 0000 pointing upwards we do a recast against that plane and we get the position so this should be working let's do a quick test up here and let's do an update just for testing so private void update on update let's just do a debug down log on this get position okay that's it let's test okay so here we are and we can see the log and right around here is around the origin and yep we do see down there the position it is close to 0 0 as I move to the right yep it is increasing on the X and on the Zed and as I move over here lowering on the X not Z so yep everything does look perfect all right great so here we have one method for doing this this is just using math just math no physics nothing like that this is really great and really simple if you have a flat game plane like we're going to have in this game but for example if you wanted to use a non-uniform Terrain mesh with different heights if so then using physics would be a better method the way you do that is actually quite simple it's very similar to this you would go inside physics and do a ray cast this one takes an array as well so we can use the same Mouse camera ray and then we can use this version of the function that just returns a out Ray cast hit for the ray cast hit this one also returns a bing so if it is true that means it is going to hit something and if it h something then we just return the rast hit go inside it and access the point this is going to be the position where it actually hits then if you want you could also add an external layer mask so you could use this version with the layer mask and use that to make sure it only hits the terrain collider and with that then Yep this would be working exactly the same but using physics so dep depending on what game you're making you have two options you can use physics or not use physics now in this case our games actually going to have a flat play area so for that we can just use a simpler just math based method and yep that's it here we have a nice function that returns our Mouse wor position now let's actually use it let's get rid of our testing update over here and now on the unit mover system over here instead of constantly moving to the right over here we want to move towards the mouse position so here let's grab the mouse position and in order to make it easy to access let's actually make the MOs one position a Singleton so back in this class let's make the standard thing for making this a Singleton now since this is an intermediate course I'm assuming you already know what exactly is a Singleton basically it's a super easy way to access a global reference of which there exists only one of them so here we can just make a public static of the Type M position let's call it instance make it a property with a public get and a private set then we just implement the normal awake for our mon behavior and on awake set the instance equals this okay that's really it now we can easily access this instance and through there then we can call this function so let's go back over here onto our unit M script and when getting the target position let's go inside the mouse position access the static instance and call get position and you just like this unit should be going towards the mouse position let's make sure to save both files wait for Unity to compile however after we compile we actually see an interesting error over here on the console this is a burst error it is telling us we cannot use burst inside of this function because inside it we are calling a managed function we are calling our M position. get instance once again when using burst we cannot access any managed data so this is why you have to be careful when not using just structs if you don't you get this issue which means the code will still compile we can head on play and it will work but it will not compile using burst meaning the code will still run just slower now right now in this example we can really just ignore this error since later on we're going to get the target position in a different way but this is a great reminder of the limitations on burst and when working with dots don't get too scared if you see some burst errors because again they don't s compilation they're really just warning to make sure that you know that burst is not working so your code is not running as fast as it could be but in this case should be working fine so let's test click on play and if there it is there's our unit moving and it is indeed moving towards the mouse so I place the mouse wherever and the unit goes perfectly towards the mouse all right awesome so everything is working perfectly but two things first of all the unit is going towards the target all the time now usually in an RTS game you want to be able to actually control it it should really only move towards the mouse position when I click on it and secondly the rotation is way too Snappy it rotates to the Target position 100% instantly we want to make it look good so let's make it smoothly rotate instead of being such an instant thing doing that is actually quite easy so over here in our unit mover system we are setting the rotation and we are setting it directly to the final rotation if we want to add some interpolation we can actually use the slurp function there's a function for it inside the math Library again that is the normal math library inside of this one we have a slurp again do not confuse that with the math F Library it is not that one it is the math Library so here we have slurp and slurp by the way means spherical interp so basically interpolates from one rotation into another one so we can use it to very easily smooth out our rotation this one takes a starting quion an ending Quan and then a time so for the start that is going to be our current rotation so let's go inside the local transform let's read our current rotation then for the Target position that is going to be the one that we are calculating here and finally we have the T for the time in this case we can just use D time multiplied by some rotation speed so system api. time. time multiplied and let's find up here some kind of rotation speed let's put it some like 10f and use it like this so then we assign our rotation into this okay that should do it and this should now make the rotation nice and smooth so let's test okay there's the unit and yep as I move the mouse even if I move really quickly the unit still moves at a relatively nice smooth Pace okay great so now to solve the other problem we only want it to move when we click for that we're going to need two things we need to store the target position instead of setting a new one every single time and we're also going to need to test for a click that is actually going to be an interesting challenge so let's do that in the next lecture hello and welcome I'm your kmy in this lecture we're going to learn how to get the unit to move to the mouse position but only when we click this requires refactoring our component and creating another non do script okay so here we have our unit rotating and moving towards the mouse position but we wanted to only move on Mouse click not all the time so let's solve that and for that we're basically going to need two things so we need to sore the target position instead of setting a new one every time and we also need to test for a mouse click now first for storing the target position as always in dots you store thata in components so let's actually refactor this move speed component to include a bit more data than just move speed let's rename this so we can right click directly on top of the symbol and let's click on rename which will automatically rename everything so let's rename this instead of move speed just call it unit mover so this is our unit mover component so rename that one and let's also rename the authoring component so let's rename it and this one is going to be the unit mover authoring okay so yep everything has a different name and now the unit mover system this one is also using the unit mover let's just rename this one over here so unit mover so yep that field has been renamed unit mover has been renamed and over here we're not using it okay so far so good then back in unity make sure the file itself did change it should be called Unit mover authoring and if we go inside the unit itself yep it should still have it and if we hit on play yep everything should still move okay great by the way here make sure your unit is not on 0 0 move it just a little bit this is important because otherwise you won't get an issue with the math. normalize if the move direction is 0000 then this one ends up with n not a number and that causes all kinds of issues this will no longer be an issue once we add the stopping logic later on the course but for now just make sure the unit is not on 00 Z so now this one let's add some more data and actually let's also rename this one instead of being value this one is going to be the move speed and same thing on the unit mover authoring move speed then here in unity let's select the unit and make sure that it has a move speed so there I go reset to zero let's put it on five and again play again and yep it still works okay great so now here on the unit mover now we can add whatever extra data we want like for example we can add the rotation speed like previously over here we were using a local variable but it makes more sense for that data that value to be defined over here so let's do a public float for the rotation speed and again let's also Define it on the authoring component so we can pass it in so our rotation speed equals go inside the authoring component and grab the rotation speed then on the unit mover system over here on this one instead of using a local variable instead of that let's use the one that we get from the things so we get the Lo rotation and then for the T we've got time down time multiplied by let's go inside the unit mover component let's read from it so let's access the value our oh and we want the rotation speed okay so now our component should have some more data and if there's our component with rotation speed let's put it a bit faster let's say 15 Let's test and yep it is still rotating with the rotation speed okay great so this working now all that's left is to deal with making sure that it only goes towards the mouse position and only onclick now technically over here on the unit mover system on this one we could add that logic so we could test over here if input. get mouse button down so when the player left clicks if so we can say the position equals the ma position so technically we could do this we could write this directly over here directly inside of the unit mover system this would technically work but then it would also become quite messy one of the main goals of dots is for your systems to be focused on doing just one thing so for this system which is called the unit mover system this one should really only be moving the unit it should not care about giving unit orders it should only move regardless of where that order where that Target position came from so let's make sure this is say focus on just that just moving units not on giving orders for that let's make another script that will basically handle the unit selection giving them orders and again we have the same question we had a while ago so do we make that a normal eye system or do we make it a mono Behavior again going back to General guidelines that I mentioned a while ago basically how you should use normal mod behaviors when we have something that only happens rarely or is not performance critical can only use dots when it's something that involves tons of units or requires tons of performance in this this case for the unit selection at most the player is going to be selecting their units let's say 10 times per second so it is not something that is going to run 60 times per second the logic for unit selection is not performance critical so for this one let's make another regular mono Behavior so let's right click on the mono behaviors create a brand new mono Behavior script for this one let's call it the unit selection manager also as a personal rule I decided to name all the mono Behavior scripts name the all manager and then for the do systems name the all system again not a requirement just a nice convention that I find very useful to follow okay so let's make a game object to run the script so a new empty game object give it the exact same name let's make sure to drag the script and reset the transform and open okay so now here let's make a normal update so private void update so the standard update and now here we do want to test for the right Mouse click and again we're going to be using the input manager so input get mouse button down Mouse button with an index of one that is the right Mouse button so again here we're using the input manager again just for its Simplicity just because it is so simple to use but later on we can refactor this to use the input system okay so here we've got a right Mouse button click and when that happens let's grab the mouse RM position so Vector 3 for Mouse RM position and we just go inside our Mouse worm position class access the static instance and call get position okay great so with this we have the mouse wor position now the goal is to tell our unit to move straight towards this point so this is actually an excellent time to learn how we can interact with the do swirl directly from the game object world we already saw the opposite over here on the unit mover system so this is an i system this is a DOT system but on this one we already manage to interact with a regular game object a regular mon Behavior we just use a static instance in order to access it now in here we want to do the opposite we want to access the dots srl from a mod Behavior script this one is going to be a little bit more complex basically the goal here is to give the unit the target position which means we want to find all the units all the ones that have a unit mover component and set their target position so to do this the first thing we do is create an inty query with all the components that we want to find so it's really the same thing that we have over here we're doing into query for various components so over here and let query for that however we cannot use system. API if we do this query for let's say the unit mover if we do this nope this does not work it says you may not use system API outside of a system basically this system API this really useful class this one can only be used inside of systems so over here since we are outside a system we need to do something a little bit different we need to manually create a query with another method so what we can do we can do construct a brand new entity query Builder Yep this one right here this is how we can build queries now this one takes in a parameter for an allocator and a bit strangely enough it is not exactly this type or the type that we're going to use the one that you should use is called allocator it is this one right here the one that exists inside unity. collections let's go ahead and use this one now allocators are very important they are basically the finding the lifetime for the memory that is going to be used by this object it is very very important that you choose the right allocator so you don't end up with memory leaks over here the main ones you're going to be using are either persistent or temp now for example here if you were to make it persistent then Unity will reserve some memory for this object and then it will keep that memory round until you manually dispose of it so if you were to make something persistent and then you do not dispose of it then over here we would be creating a new object we would be instantiating new memory doing that every single time we press the mouse button that would essentially end up with a memory leak and the game would eventually crash so if we were to use a persistent allocator then we need to make sure to clear the memory but we have other allocators and the important one is over here temp this one is going to be the shortest one this one is going to be automatically disposed at the end of the frame so you don't need to manually dispose this one in general you should always pick the smallest allocation possible it is more performant to make a temp allocation as opposed to a persistent allocation so while technically over here we could use either one we could make it persistent and then dispose of it or alternatively we could make it persistent then cach it inside a field both those options would work but using the super simple temp this one like I said is automatically deallocated so in this case where this code isn't insanely performance heavy for this case using temp makes it work perfectly fine whilst being quite a bit similar so let's go ahead and use the temp allocator okay with this we have created the new anti query Builder and now with this one we can do similar to what we did on the system API query we can add the components that we want this query to include so so let's call the function with all to include all the components that we want to include inside of this NT query in this case we only want to set the unit mover Target so let's just grab the unit mover and if that's it here we have a valid enti query Builder but like name implies this one only Builds an anty quering it is not an inti query itself so after defining all the components that we want to use afterwards let's call the build function and this is what we'll actually create the final in query and this one takes in a parameter for an in manager so this means we need to access the en manager for our world and the way we get that is actually quite simple we can access the world class this one exists inside unity. enties and then inside that one we have the default game object injection World basically dots can have multiple worlds this is how for example dots multiplayer works you have a server world and the client world so in advanced use case you can create multiple worlds and do some really complex things but by default it is always going to have the default game object injection world this is the world that we've been working on so far when we constructed the new subscene inside of our Hier all the objects over there that are going to be baked inside of this one world so we can access this default world and then inside of it we can indeed access the en manager so let's grab the en manager just store it en manager and it's exactly going to be that one and then over here we construct the query with all of our components so we want the unit mover component and we build an inti query and it's going to be the inti query for our inti query all right yep that's it so here we have our final int query that we want to use now all we need to do is really just cycle through it now there are two two made methods for cycling through an nty query if we go inside the nty query inside we see the functions there was one called two entity array like name implies this one will create an array containing all of the entities that match this query it will have the objects of type entity itself or alternatively the other one we have is two component data array this one will return array containing references to a specific data component by the way both of them both this one and the two anray both these will return the same size the anti query does not change so this means that we can actually cycle through one of these arrays and using the same index we can either access the entity or we can access the component data so if you had a query with multiple component types and then you want to cycle through those multiple component types you would just call this function multiple times for each component type you want and then again everything will be on the exact same index now this case we really just want to update the target position on our component so let's use two component dat array and grab the unit mover yep just like this although one very important thing here make sure you're using this function to component dat array not the other one there's also this one two component array this is not the one you want to use this one is meant for working with classes and returns a normal array the one that you want to use is this one two component that array which returns a native array and this one does work with I component so don't make this mistake make sure you use the correct function and yep so this one is going to return a native array of our component type so native array of our unit mover component so let's called the unit mover array and since this one is going to construct an array because that we need to actually input the parameter and again it's going to be our allocator so again same thing that I said a while ago you can use whatever allocator you want but in most cases you probably want to use temp okay so yep so this is going to return array that contains all of our unit mover components and again note how it is not a regular array so it's not a unit mover array like this nope instead we have a native array now this is a type that exists inside unity. collections namespace this is similar to the normal C array but this one is made specifically to work with dots and burst whereas normal C array those are objects so you cannot use those inside a burst you can use native arrays directly in there okay so with this we have our unit mover array now this going to work just like a normal array so let's do a cycle through it let's do a four and I equal Z while I under the unit move array. length i++ and the reason why I'm using a four instead of a 4 in is just in case in the future we want to use that index to go through either the anti array or some other component so okay so with this now we can grab that component so we can grab that one on this index and that is going to be a unit mover unit mover yep here we are reading the component and now let's just s this unit to go towards this position so that means we also need to refactor our unit mover component we need to have some kind of Target position so let's make another field make it a Flo three since this is a position for our Target position and FL three exists inside of the unity. mathematics so let's go ahead and use this one in this case we don't need to add it to the authoring component this one is going to be set manually through code and then over here on the UN mover system instead of defining this target position instead of that let's just go inside the unit mover component read it and read the target position so yep now this unit should be moving towards this target position and over here back in our selection manager on this one we can just go inside unit mover set the target position and set it to the mouse wor position all right yep like this let's go ahead and test but before you do I want you to pause the video right now and ask yourself will this work will the unit actually go towards the mouse run position when we right click just pause the video and think about it for a second okay so let me just save all the files make sure they all compile let's wait for compilation to finish and now let's test so let's head on play okay the unit is going to 0 0 Let's just ignore the rotation now I right click and nope nothing happened Target position is not changing I can inspect the unit and go over there onto the runtime mode and we can find our custom unit mover component there it is and yep Target position is on 0 0 0 so even as I right click nope it does not change so the problem is right here I wonder if you managed to notice exactly what the problem was so the issue is once again here we are working with structs and not classes it's a whole thing about value versus reference types here when setting the target position when we do this we are just modifying this copy we are modifying the copy stored in the array and note how this is not a value RW so like here on the Move system the reason why we can modify the fields inside of it directly like for example here the local transform modifying the rotation the reason why this works is because we are using the special type the ref RW but over here on this code we just have the normal unit mover type this is not a reference to anything so over here we are just getting a copy by modifying this one we are just modifying the copy and not actually modifying the data that is stored in the entity so this is why the unit was moving this is why it wasn't updating if we do want it to update then we need to modify it and after we modify it we need to save that data back onto the entity so one way to do that is to access the entity manager so I'll access that one The Entity manager and then we call the function set component data this one takes in an entity so let's actually get the entity as well so let's go inside the entity query and inside that one let's call two NT array once again let's use the allocator temp this one is going to return a native array native array of entity for our entity array and now with this one like I said it's on the same index so in order to update the component on this same entity let's access the enti array on the same index and we're going to set it to this new unit mover component so here we grab the unit mover we are grabbing just a copy then we are updating Target position just on that copy and finally over here here we are actually updating the value directly stored on the entity so yep like this let's save and over here the game is playing I right click and yep now it does work right click and right click and yep down there we can see the target position that one is indeed updating as I right click okay great so as always always remember how when working with structs you are usually dealing with the copy and not the original data so if you do something like this without using the special rep r w type without that you are likely working with a copy so if something does not change if something does not happen as you intended to always think about this cuz this is probably the problem it is probably because you are modifying a copy and not the original position in memory okay so this code is working but let me also cover one sneaky issue here so here we are reading the component and then we are updating it but technically we could remove this we could get rid of this and then over here just create a brand new unit mover component and inside set the target position equals our Mouse World position so yep this technically looks like it should work and it should also be faster because we are not spending any time reading the component we're just cycling through it and just setting it to New Target position however let's see does this actually work let's test so here we are and I right click and nope it does not work rather actually it did work if we inspect the unit if we scroll down and we look inside the component yep it did update the target position so if I right click you can see that one is indeed updating correctly however the issue is that while the target position is being correctly set over there the move speed and rotation speed those are being left on zero this is yet another very important thing you always need to keep in mind so over here when we construct a new instance of this type like this we only gave it a value for the Target position we did not explicitly assign a value to the move speed or the rotation speed and if we don't do that then those fields are simply going to default to zero so that's what happened here this is another thing you always need to remember always need to be aware of if you only want to update a single thing inside a component if so then instead of constructing a brand new component instead of that you should do what we were doing a while ago so you should first read then update and then update the data so first here we are reading we are updating the copy and then we are saving that copy directly onto the end this way you can modify just one field and it's going to keep whatever other data is inside of this component also just one more note here so this code is working it updates the target position does save it on the entity in this case this is perfectly fine since this code is not going to run constantly this is only going to run whenever we right click on our Mouse but technically over here we are writing to our component for every single entity meaning if we have 100 units selected we are going to call this function set component data 100 times like I said in this case it's perfectly fine because this code is going to run pretty regularly but if you really want maximum performance if so then another alternative to this is we can cycle through the unit mve array we can update it with new Target position and then over here we do not set the comp data instead we just save the new unit mover directly on the array again we need to save it back otherwise we are just working with the copy so we are updating the data that is stored inside of this array but by itself this will not update the entity this is just modifying this local array but if we do this which is going to be pretty fast after this we can go inside the entity query and inside this one there's a really nice function called copy from component that array this one takes in a nav array so we can pass in our unit move array and if just like this this fun function over here this will basically update the data on all the components that match this entity query so instead of doing one right instruction per each entity instead of that we update all the data inside of this array and then at the end after doing all that we do pretty much just one wri instruction and just that one is going to update all the entities with all the data inside of this array so now if we test everything should still work the same so here we are and I right click any up it does change position it does move everything works perfectly fine all right awesome now just for fun let let's duplicate our unit and test with a whole bunch of them so here let's just manually duplicate them a bunch of times let me select the unit so just put on over there over there and so on by the way this is really just a temporary test so that is why I'm not bothering to make this unit into a prefab just yet we're just doing a simple test okay so with this I have a bunch of units let's set on play and if there they are moving and I right click and Y they all go there they all go up there down there and so on they are all following the target position so I can give orders to all of my units again that's the whole thing about do it applies the same logic to all the entities that match the query regardless of how many entities you have all the ones that have the query are currently getting the target position assigned so they all go towards there so y with this everything is working great now if we leave them on a Target position they still get a little bit messed up that is because of the physics they're constantly trying to go to the exact same position so things get a little bit messy we're going to solve that later on when we Implement some stopping logic and multiple move positions and collision avoidance and so on we're going to handle all of that in the future but so far everything is working pretty great we can click and all the units go exactly where they're supposed to and in this lecture we also learned the very important concept of how not everything has to be dots based you can make some dot systems and you can make some mono Behavior systems everything works fine we also learned how to interact with the dots worldl from the normal mon Behavior world so we've already learned quite a lot over here let's just remove these testing units okay they are working fine all right let's just leave it one and right now our game our basic logic all this is working good but but so far we're only been using the main thread so we're not yet taking advantage of all the massive power that dots brings now that the move code is fully working now let's learn how to use the job system and verse in order to make this move code insanely fast so let's learn how to do all that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to create a job and use burst so our movement code is insanely fast we're going to look at the results before and after to see the really massive difference that it makes okay so here we have our unit I can right click and tell it to go to some position so yep everything does work and here we have our unit mover system so all of our logic is over here on update we're doing a simple for each cycling through the query meaning that all of this code all of this is running just on Main thread so for example if we have a CPU with 16 cores then 15 of them are going to be completely idle doing nothing just wasting time only one of them is actually going to be working ideally we don't want that ideally we want all the cores in the the entire CPU to be doing some work so our game is as performant as possible now in order to write multi-threaded code we could use normal C code we could manually create threads and give them tasks but like I said on the lecture on what is not writing good native multi-thread code is extremely difficult and it is very easy to make all kinds of mistakes so thankfully Unity has created the job system which makes that process much much easier so let's see how do we create a job now first thing we do is Define a struct and we can Define it anywhere but it makes sense to Define it next to the system where we're going to use the job so here on the exact same file let's define it although if this were a job that would be used in multiple places then we would probably Define it in a proper file but this unit mover job this will only be used over here by unit mover system so it makes perfect sense to Define it right here okay so let's define a struct so that's the first thing then jobs are also going to have some Source generation so let's make sure to Define it as a partial struct then we use some name let's call it unit mover job personally I like to opin job to the name but again not a requirement and now finally we Implement an i job interface now you can just write I job and you can see all kinds of interfaces you have these are all going to run slightly different remember how I said that all the components that makeup dots do not have to be used together all at once so you can write multi-thread code with the job system without using entities at all in those scenarios when not using entities when just doing some random normal multi-thread code for that You' use either iob or iob 4 those are the two main ones but when working with entities for that we have the super useful iob entity this one is going to be really easy to use technically we also have iob chunk this one is also related to entities but this one is for more advanced use cases it is more performant but requires you to do a little bit more setup whereas the I job entity this one runs super fast and is really easy to use so let's use this one I jop entity let's go ahead now for this to work we really just need to write a void execute function so if just like this and now on this function on the parameters over here we include whatever components we're going to need so let's copy exactly the same query that we have up here so we need the local transform the unit mover and the physics velocity so let's add those so local transform local transform then we have the unit mover unit mover and finally the physics velocity okay that's our three components and now here we also need the same thing that we defined up here we need to Define them as either read write or read only however down here on the job this one uses a different syntax although actually technically you can use the same syntax so you can use refr W technically you can use this but the unity docs they recommend something a little bit similar so instead of using that instead if we want to make something as read write for that we write the ref keyword this is the ref C keyword this one basically means that this field won't be received as a reference and since it is received as a reference even though this is a struct it means we can write to it and then if we want something as read only like for example the unit mover we only want to read this one for that we use the N keyword so yep rep for the local transform so we can modify it in for the unit mover for read only and for the velocity we want to write to it so let's make it as rough okay yep just like this again technically you can use rrw and ref in it will work but the docs recommend this syntax instead so like this we have defined our execute method and basically when we set the job to run it will automatically create a query with all of these components it w do all of that just like the system API up here and will'll run the execute for each entity that matches that query so now our goal here is to do literally the exact same logic so let's just copy the same code so just copy down here paste it and the only difference over here we don't have the refr W or ref rro so we don't go through the value rro instead we just modify directly so just get rid of this get rid of this one this one this one this one this one and this one okay so yep so here we have exactly the same code and the other difference is what we see here we have an error and this actually the general limitations that exist inside of jobs meaning that jobs mostly have to be self-contained meaning they cannot access data outside it now technically you can you can pass in a array and then access different positions in memory and something like that but in general jobs are self-contained meaning they need to have all the data that they need in order to execute their function now this limitation of jobs being mostly self-contained this limitation is actually what helps write super fast multithread code without causing all kinds of chaos if the job only works on thata that the job has then it's super easy to make it run parallel in multiple cores at once so the era that we have here is because we cannot access the time. Del time from here and the way we solve this is super simple we basically just Define a field on job so up here let's just find a public float Delta time so just a perfectly normal field and then down here instead of going through system API we just use that field so that's it no more errors so now basically when we construct our job we simply need to assign the D time and everything won't work perfectly so let's actually do just that so up here on the on update let's construct a brand new job so a unit mover job let's go on unit mover job and construct a brand new unit mover job and now inside of it for Delta time over here we can Le access system api. time. Delta time and Y so that's our job all set up let's make sure to comment out the other random query code okay so up here we have defined our job now all we need to do is really just run it and we actually have multiple ways of doing that now the most straightforward one is go for the init mover job and just call run now this one will run the job directly on the main thread so this kind of loses the main point behind jobs you should probably only this one just for testing or debugging essentially this will end up pretty much the same thing as we had previously the main goal of jobs is to make multi-thread code so usually the one that you want to use is the one that is called schedule parallel this one will schedule the job to run on all the entities that match the query in parallel meaning if you have lots of entities it will run the job on multiple threads at once and each entity won be responsible for updating a few entities although quick note just something to keep in mind which is actually something that I only learned after doing a bunch of research this one schedule par this will split the logic in multiple jobs based on the number of entities so this is really perfect if you have tons of entities doing some logic but if you have just a handful of entities so if you don't have many but you have a complex job if so they are likely all going to run on the same thread because you don't have enough entities to split it so just keep that in mind that's how the job system works if you have some really super complex logic but you're only running it on a handful of entities if so then this will basically run just on one thread so in that case you probably want to split the logic into multiple jobs yourself okay so just with this we can test and see that it works so here's our job we construct it we schedule it and let's comment out the rest okay let's save and over here let's hit on play and try to move the entity and yep everything still works perfectly all right great so the unit is still moving exactly the same except now it is moving using a really nice job by the way what we just did here is actually what we're going to do a lot throughout this course and what you should probably do when building any kind of new system first make it work just with the normal for each just with normal main thread code first get it working like that and then once you have that logic working then you refactor it into a super fast job okay so this is working however we still have one thing missing we're currently not using burst now adding burst is thankfully super simple all we need to do is up here on the job itself let's add the attribute burst compile and yep that's it that is literally it just by doing this our job will now run with burst enabled which is going to make it insanely fast so let's say save and let's test just also here in the entity make sure you go into the menu burst and make sure the compilation is enabled if you disable it then even if it has that attribute it will not use burst so make sure this is enabled Let's test and there you go everything still works fine now let's actually see difference that all this makes in real terms now this code that we have here this one is really simple so it is going to run insanely fast no matter what so it's actually a little bit tricky to see the results just because again everything is going to be insanely fast for a test I'm going to duplicate this unit a ton of times and before I do let me just get rid of the capsu collider just because right now we really only want to test our movement code not any physics system just make sure that it's still working and yep it still moves okay great so now I'm going to duplicate this into a ton of units okay so here I duplicated 10,000 entities now my Unity editor is a little bit slow so to make it a little bit faster let's use the power of dots let's close the subscene for editing and again now everything is being baked into super fast binary data so now there it is and now the unity editor is working a little bit faster and we can verify that we have 10,000 entities so let's head on play and down there we can see yep the in mover system is working on 10,000 entities okay great now over here in our code let's make it run the slowest possible let's use the normal for each without jobs so let's actually comment out this one right here comment out the job and let's uncomment out the 4 each okay so we're going to use the normal code let's save this so we are not using jobs and also let's go up here and make sure to not use burst okay now for seeing how fast it goes let's go into window then go into analysis open up the profiler so here it is now I'm going to H on play and capture a certain frame so they're all moving capture a frame okay here it is and let's see how fast it is and yep here we have our unit mover system in total running on 10,000 entities and it is taking 9.13 milliseconds okay that's great and right now it is not multi-threaded so we can see down here all these threads all these jobs all of them are empty so this is where we can see all of the threads that I have on my PC see all of these are completely idle just wasting a ton of time whereas only the main thread that's the only one that's actually running this logic so this is normal C code just running on the main thre okay now back in code here now let's enable jobs so let's go ahead comment out the system and let's enable our job like this so let's see with this although here let's also make sure burst is disabled okay burst disabled just using jobs let's play and now let me move them and select a certain job okay so here's a frame and now got to zoom in in order to actually find it and yep it is actually right here I had to zoom into the maximum in order to find it like I said the code is super fast so even though we have 10,000 entities right now it is running on 01 milliseconds as opposed to the 9 milliseconds we had previously now over here we can see our jobs so we can see all of our work of threads and we can see all of them yep the code is being split across all these threads and all of them running at the exact same time so because of that previously we were taking 9.1 m milliseconds whereas now if we add them all together 30 instances over 30 threads in total it is taking 8.3 milliseconds but in reality it's just taking 0.3 milliseconds because again all of this is all working at the exact same time so as opposed to having just one thread and running all the logic for unit a and then Unit B instead of that both threads are working at the exact same time so within the same amount of time they are running twice the amount of work so right away you can see the huge Improvement you get with multi-threaded code by taking advantage of all the cores in the CPU your code can become massively faster like it's not literally just two times faster or three times faster but literally over 10 or actually over 20 times faster from 9 milliseconds to3 milliseconds and now for the final piece of the puzzle let's enable burst so over here we create the job and over here we make sure we add burst compile then in unity let's go into jobs and enable burst compilation okay that's it let's hit on play again and now let's find what and you can already see over there in the graph how quickly it moved now I need to zoom all the way out then all the way back in okay let's see if I can find where it is okay I found it so right here for scheduling the job this one is pretty much as fast as it was long ago which is pretty much instant so scheduling the job just takes 0.014 millisecond again keep in mind these are milliseconds not seconds it is taking 0.01 milliseconds so with burst enabl scheduling a job is pretty much instant now let's see if I can find the exactly where the job is being executed and yep it's actually over here and yep here is the job and we can see all of them running in parallel and biting burst we got yet another 10x performance improvement with just the job system it was taking 0.29 milliseconds and now inverse it is taking 0.035 milliseconds like it says here the total amount of time is 0.84 so that's the total amount of time but since it is running in parallel the whole thing runs in 0.03 milliseconds by the way the green colar over here that's how you can easily see which things are using burst and which are not green means burst so here you see the insane power of d honestly no matter how many times I see it I can't help but be impressed as long as you follow the data oriented design and you keep in mind some limitations as long as you do that your exact same code can run multiple times faster and again it's not just 10% 20% faster or even 100% no it is 10,000% faster it really is insanely impressive watching these results always impresses me so originally our code running on a single thread that one was taking 9.13 milliseconds then we added multi-threading with the job system and we got it down all the way down to 0.29 milliseconds and then finally we enabled burst and in the end the exact same code runs in 0.035 milliseconds so we went from 9 milliseconds to 0.03 I don't even know how many percent that is faster but it is something like 300 times faster again for the exact same code doing the exact same logic and again what I mentioned a while ago what we did here is what we're going to do throughout this course and what you should do meaning get your logic running just on the main thread just using a for each system query get it working then refactor it to use a job system apply burst make it schedule as parallel do all of that and all of your code will run insanely fast okay so yep everything worked let's just clean up our testing scene and by the way here we can see all the units really nice you see 10,000 units all of them moving for the same place okay great so now let's clean up this test we really don't need 10,000 units just yet so I'm opening up the subscene going to select all of them and get rid of all the units except for one any if we back to having a single solitary unit press on play and yep everything still works perfect let's just make sure we remember to read the capsule collider so the capsu collider let's put it on a y of 1.1 radius of5 okay and height of two okay our unit is back now just before we end this lecture let's do just one tiny thing let's add some simple stopping logic so right now if I head on play you can see the unit gets a little bit bugged that is because it is constantly trying to go to the position 0 0 but the unit is already on there so it gets all messed up thankfully adding some stopping logic is actually quite simple so over here in our job we are calculating the move Direction so the target position minus the current position and now before we normalize this Vector before we do that then this Vector actually has a size it actually has a length so we can grab the move direction. length although actually it's not done like this we go math we use math. length and we have either length or length Square this is actually an important thing and it's yet another performance thing basically the way the actual value the actual length is is calculated by doing that is first by calculating the length square and then by doing a square root on that value to get the final length now doing a square root that is a relatively expensive process so if you don't absolutely need the actual value then really just use a square this case we don't really care we just want to compare if it is close enough so we can just test for a squared value so let's use this one that is super fast so we get the length of the move Direction then really just want to check if it has reach the target position so let's define a float for a reach Target distance Target distance squared and let's put it at something like two units then we simply do an if if the length of this Vector if it is under this amount then we have reached the target position and if we have reached then we simply just want to stop moving and the way that we do that is super simple we just set the linear velocity back into zero so for this one float 3.0 we set it to that and of course we stop executing so let's add over here a nice return okay so yep that's it the unit should now be stopping so let's test and here we are and right away we don't see that bug if I click to move go there and up does stop as it gets within a certain distance okay great all right so here we'll learn how to convert a normal main thread system into a super performant multi-threaded burst compile system this makes our movement code super efficient but so far we have no control over which units we want to control right now we're just using the same unit or all the units at the same time so let's handle a way to select our units individually and let's do that in the next lecture hello and welcome I'm your kodm in this lecture we're going to learn how to select our units so we can choose who we give orders to we're going to use what is called an enable component which will let us toggle it on or off depending on the state and depending on that state we are going to give orders to those selected units okay so far all our Logic for moving the unit works I've got just one unit here I can click and yep the unit does go towards the target position it goes there perfectly it works with one unit and also works with multiple units all of them go towards the target position now before we make some gets again it's probably time to make this unit into a prefab so first of all let's keep things nice and organized let's make a new prefabs folder folder called prefabs let's drag the unit on there okay and also let's select the unit and over here for the collator let's actually make it a trigger just to make it so that there we don't have any issues with collisions right now again like I mentioned we're going to add collision avoidance and some proper move positions later on but for now let's just enable this so we don't have any issues and make sure you make this a trigger directly over here on the prefab so it should apply to all un not just this one unit okay now we can duplicate them so let's duplicate a bunch of them position them a bit like this just having a bunch of different units okay great and if we test Yep they're all still moving click and yep all of them go towards Target position okay great but that's actually a problem all of them are moving now in an RTS game you really want the player to be able to control which units to move instead of just moving all of them all the time so we need some way to tag some units as being either selected or deselected then when giving the move order when doing that we can make sure to only give those move orders to the units that are actually selected now when it comes to tagging units we have multiple options the first one is with a simple component tag let's create one just to see how that works so in our authoring scripts folder let's go ahead create and by the way for making a new authoring component we can create a monab behavior script and go through that whole writing process or we can go over here into entities and this one already has a baker script so let's see this one just see what this template has let's call this the selected authoring okay let's open and see and Y this is what it creates by default so it creates a monab behavior class and then creates a second a baker class that implements Baker and the bake method now honestly personally I still prefer the format that I have over here I think this one makes it look a little bit cleaner so I've got the authoring class it has the public everything looks nice and proper we've got the biger class inside of it and then the component down here so technically you can use this template if you want but me personally I prefer this format over here so I'm going to basically follow this so over here on this one first of all I like to be it so let's make it as public then we've got the mon Behavior then inside we've got the baker class I like to call this one just Baker and make it public okay so yeah but again personal preference personally I prefer this format okay so now let's make our actual component let's make the usual thing so this one needs to be a struct then for the name let's call it selected and then we Implement I component data and that's it that's all it takes here we have just a tag component meaning it's a normal component a normal I component data and it simply does not have have any films at all it really just exists so it can be used to tag objects then over here on the B we really just set it so let's grab the entity let's call get entity and for the transform usage Flags let's default using Dynamic okay then we call add component we're going to add an component onto this entity and it's going to be a new selected component yep that's it super simple we've got our authoring component we've got the Baker and we just add our component which does not have any field so this one is just a tag component let's go ahead and save this and now let's add that component to the unit and also again make sure you select the prefab so that it applies to all units so don't add it to just one of these units let's add it to the prefab itself so over here let's drag the select authoring component yep just like that and just like this we can already see what that does so let's select one of the units inside of our subscene this one yep does have the select authoring and on the inspector let's swap it into runtime mode and Y right here up top here we have a section for tags and we can see yep here we do have our selected tag okay great so this is how tags work tags are really just empty components they don't have any extra data and they show up over here on this special section so this is one way you could handle the selected logic and basically for selecting units we would add this component then for deselecting we would simply remove this component now technically that would work however adding and removing components is what is known in dots as a structural change and that is something you should actually avoid as much as possible because it is a quite expensive operation basically the way dots works in the background is it creates what are known as entity archetypes so an archetype is a unique identifier for all the entities in a world that have the same unique combination of component types so for example all entities in a world that have component types A and B those share the same archetype and then entities that have components a b and c those have a different archetype this is a really important thing to know dots in the background does a lot of work to place all those entities of the same archetype together in memory again that's how it works so fast but since the archetypes are based on a specific set of components because of that if you add or move a component you are going to be changing the archetype and doing that like I said is what is known as a structural change and like it says here moving entities between archetypes that is a resource intensive operation and reduces the performance of your application essentially when you do a structural change like for example you have types A B and C and you remove the C when you do that then whatever entities used to have a and C now just have a and b so now those entities need to be copied onto the entity archetypes that have a and b basically doing a structural change requires lots of moving things about in memory in the background this is a resource intensive operation so you should avoid using it as much as possible so for this particular scenario since we're going to be selecting and dis selecting units quite a bit for that instead of adding or moving a component which again would trigger a Str change instead of that we're going to be using something really awesome called enable components this is basically a component just like this except it's as if it has just a balling inside of it that defines whether it's enabled or not but unlike just storing a regular Bowl inside one of these components unlike that if you have an enable component those can be used in many special ways without having to read the entire component data now the way we make something as an enable component is super simple we'll literally just Implement another interface it's called I enable component and if that's it we don't need to add any extra data just by adding this it will already work so let's go ahead and save let's wait for it to compile and then look at the entity and yep there it is there's our selected component and now you can see it does have a nice checkbox this checkbox lets us easily either enable or disable this component and since the whole thing we're doing here is just flipping a bullon bit we are not adding or moving components so because that setting this to either selected or deselected will not trigger a customly structural change okay so we have our nice enable component now let's see how this actually works inside a query so let's create a simple testing system just to test out some things so inside the systems folder let's right click go inside the entities and create new eye system called just testing system okay so now here let's get rid of the create and Destroy we don't need those okay so now on the update on this one let's go inside the unit mover and let's basically just copy the for each that we had here just to copy basically that query so let's copy and paste it over here okay everything worked again if you're seeing some errors it's probably because your Visual Studio did not automatically write the using statements so make sure those are on there and this works okay great except here we don't want to do any of this logic instead let's just count the number of units that this query applies to so let's do an INT unit count let's defold it to zero then on the for each let's increase it Plus+ and finally do a debug. log and let's print out the unit count as something and by the way this is actually an error that happens every once in a while basically when I wrote debug instead of implementing Unity engine for some reason visual Studios fall into importing this class system. Diagnostics that is not the one that we want we want the debug class that is inside using Unity engine like that and we have the normal debu log okay so let's run this and see how many units have all of these components it should be the same number of units and Y here in log we can see we have eight entities that match those components and along here we can see okay we have 1 2 3 4 5 6 7 and eight okay great everything is correct now let's include our enable component inside of this query so one way to do that is to literally include it in the query so over here let's add another component we're going to go with ref r o and let's choose the selected component then let's also add it up here for the selected okay yep like this let's test and again this burst error is normal that is because we are doing a log on that value but again it's just a burst error so let's ignore it and play and yep it still says the exact same thing by default the component is going to be enabled so it makes sense that it still says the same number although actually we can modify this so over here we can add the new select components but if we wanted them to default of being not selected for that over here we can call set component enabled this one pass in the entity so our entity and then let's set it as false and for passing in the component type we just need to use generics so pass in the selected compon component and set it as false so let's save any y now they show zero units and if I select one of those units and over here on the inspector make it in runtime and we can see over here the selected and we can manually toggle this box and as I toggle if there you go that one goes to one toggle again and goes down to zero so yep that works and again remember one very important thing is how whether this one is toggled or un toogle The Entity still has this component it still belongs to the exact same archetype except now this component is simply marked as either enabled or disabled and by seeing the number Z here we're actually already seeing another interesting thing over here in our query we're querying for everything that has a selected component but note how if it is disa this one actually says zero that is because this query over here when we query for something with a sid component or any enable component when we do that that entity is only included within this query if that component both exists and is enabled so if the component is disabled this code will not run for that entity it needs to be present and needs to be enabled alternatively if you wanted to query for entities that have have a enable component but have it disabled if so then instead of this let's get rid that one and this one right here okay back to what we had previously now we can add the option with disabled and pass in the component so selecting so let's select this and yep there it is eight now that quer is only included entities that have that component disabled and right now by default all of them are disabled if I set this one as enabled there you go now it's say seven so like this this query will only apply to entities that have the component and have it disable a if it does not have the component or the component is enabled if so then it does not run this logic and yet another thing we can do is simply query if the component exists on the entity so for that we can use WID present let's see and if there you go now it is saying eight and if I go into one of these and I set it as selected yep it still says eight so the entities are being included within this query regardless of the state of the actual component enabled or disable does not matter as long as the component exists on the entity it is included within this query so these are the various options that we have for dealing with enable components as we go on in this course we are going to use quite a lot of these options so now that we can actually select the units now let's actually use that selection logic within our move logic now thankfully like we saw it's actually super simple let's just go over here on our testing system and comment this out let's leave the file created just in case we need to do some more testing in the future and now let's go over here onto the unit selection manager this is the code where we are giving orders to our units and over here for the query that we are constructing we are just looking for the unit mover component so in order to be able to give order just the select units that's super simple just add a comma and let's also include the select component and again like we saw by default this query will only include entities that have that component enabled so that's exactly what we want and just like this without modifying anything else it should already be working this real will only include entities that have both a unit mover and a selected enable so then on logic over here just runs within those entities that match that query so let's test okay here we have our units and if I right click and nope not a single one of them moves okay that's great that's exactly as intended now if I select just one of them let's say select this one and over here on the inspector I'm going to manually set it as selected and now I right click and if there go now just that one unit moves just one that is selected that is the only one moving now if I go select a different unit now Mark this one as selected and click and yep there you go now both selected units are now moving all right awesome so our basic selection logic is really working we can toggle this SL component and depending on that we are moving whatever units we want to move now in the next lectures we're going to make it slight B with the mouse instead of manually clicking over here on the inspector but for now this is looking good it's working so let's just add a visual to it for that let's go into our unit and again let's make sure we work inside the prefab so it applies to all of them so let's double click on this prefab go inside of it and now let's right click on the unit let's create an empty child game object call this the selected and now let's apply visual so here we actually have two options so the simplest one is to add a Sprite renderer and by default let's select this circle Sprite so there it is right there let's just rotate it to face upwards and make it a little bit bigger okay something like this now let's go ahead and save the prefab let's just increase it on the Y by a little bit like 0.1 just so it doesn't collide with the floor let's go ahead and save the prefab and yep all the units have that press on play and yep they all still work perfectly so this seems like it's working our Sprites are being rendered however it is not actually being rendered by dots like I mentioned in the first few lectures only a few built-in components are automatically supported by dots mesh rendering works so our mesh is over here here those are being run by dots physics also works that one is also running on dots however for rendering Sprites if we actually select one of these objects so let's select this select game object and we'll look over here for the components and we see these strange components companion link companion transform basically this what happens if you bake an entity with some component that isn't yet supported by dots it creates all of these companion components and what these do is essentially the game keeps both the game object and the entity both alive at the exact same time the entity will simply Drive the game object Behavior so this is working but it's just not as efficient since we are busily back to using Game objects we have an entity but the entity is linked to a game object now in this case our solution is actually pretty easy all we want is really just render Sprite so instead of using the Sprite Rend component instead we can just use a mesh render so let's go back inside our prefab unit and for the selecton instead of using a Sprite render get rid of this one let's add the simple the mesh filter and the mesh render then for the mesh let's choose a default quad mesh and for the material let's go inside the materials folder and Y here is the select material let's go ahead and select it and yep there you go right away it does work the only thing is I believe this one is pointing downwards yep so let's just flip it over so make sure that over here on the rotation yep let's put it 90 on the X put it 0.1 on the Y and for the scale let's make it a little bit smaller so let's say on Two And yep that's it now since we are using a mesh filter and mesh render which again they work with thats because that this will be using the super fast start render just like all our other meshes so let's go ahead save the prefab go back outside and if there it is all our units with all rendering being done and we can select the selected and Y it does not have any of the companion components it has the normal rendering components okay so with this we have added the visual now let's show or hide it depending on whether the unit is selected or not and this is actually an interesting problem to solve our visual is over here it is a child object meaning it's actually attached to a different entity than the one that has the selected component so as we are doing our query for the select component we are going to cycle through just this parent entity it is not going to cycle through the child one that has the visual so as we select or deselect in order to update the visual we basically need a reference to that visual entity from the parent entity now thankfully this is actually pretty simple to do we can go here on the slide component and directly on the component let's set a new field let's make it of type entity and let's name it the visual entity yep just like this so now the question is how do exactly do we get that reference and the answer is simply through the baking system however if we were to just add an entity field directly up there if we do this if we save if we look over here in the editor for the selecting nope it does not have that field if we make something of type entity it does not show up over here in the inspector however if instead of making an entity let's make this of type game object called the visual game object if we do this yep now it does show up a normal game object field so now we can assign it and again make sure you're working inside the prefab so let's open go inside the prefab and over here now we can just click and drag the select game object and yep that works let's save let's go back outside okay so now we do have this field assigned with the correct reference and now the question becomes how do we convert a game object onto an entity and once again thankfully because of the baking system the answer is super simple we just use literally the exact same get entity function so over here when constructing is selected let's assign that one so we're going to want to assign the visual entity and over here we call get entity and for the first parameter we pass in the game object we want to convert so let's go inside the authoring component grab the visual game object and then for transform usage Flags let's make it Dynamic and yeah that's it so this will basically take this game object and convert it onto an entity and assign that entity over here on the visual entity field now we can verify that this did indeed work let's save it and over here in the inspector again make sure you drag the reference but make sure you drag it from inside the preamp and now if we select one of these entities over here in our Hurrican and if we go onto runtime mode again slight bug let's select a different one and there you go it do show up and now we scroll down and if there's our selected and we can indeed see it does have a reference to the selected entity that's the entity with ID 129 so we can manually go inside of this one select the selected and see yep entity it is indeed 29 all right awesome so with this we have a component and that component does have the correct reference to the visual entity that we want now with that we have all the info we need in order to show or hide it so let's make a system to do just that so on our systems folder let's right click go into create create a new eye system make this the selected visual system and over here on this one let's cycle through all the entities that have a selected component so we're going to do system api. query so the same thing we already saw let's grab the selected just for reading we don't need to write anything to it right now let's grab the select component so that's going to be our query and let's put this inside a 4 in for the ref Ro of our selected component and we have the selected in this query okay so this is going to cycle through all the entities that are selected again keep in mind that whenever you include a query it is only the entities that have that comp component and the component is enabled then for actually showing your hiding for that we're going to be playing around with the scale on the local transform so let's go here onto the slide component and let's also Define a field for the show scale basically how big we want this to be if we want to hide it we're going to put it on zero but if you want to show it let's put it on something and let's also expose this over here and pass it in on the baker okay like this let's save this one just set it in the editor so here in the editor let's select the prefab itself let's scroll down and for the show scale let's put it on two because that was the two that we used over there okay great so back in our slide visual system here we have the query running through all the entities that have a slide components and now we want to grab the local transform for the select visual however again it is the local transform of the visual entity meaning it is not the one inside of this query this query is basically going to give us the parent but we want the local transform of the child visual so the way that we grab a component for a different entity the way we do that is we access the system API and then we have a bunch of get component functions we can do do this one which is just going to return our component but in our case we actually want to get the local transform to then modify it so let's actually use this one which returns a ref RW of that component so let's call get component RW we're going to grab the local transform component and for the entity that we want is the one that is inside selected let's read the value and read the visual entity so yep this going to be returning a refr W Local transform for the visual local transform okay we have this one and now with this we can simply make it visible so let's go inside the value r W for writing and let's set the scale go inside the selected let's read the value value r o and let's grab the show scale so this code right here should be making the units that are selected actually visibly selected although right now you might be thinking an interesting thought you might be thinking isn't this code actually losing the benefits of dots since we are essentially accessing a reference that points to a completely different position in memory and the answer is yep that is indeed correct technically since we are getting and setting a component on a complet different entity that is not within the squaring because that this code will not be as fast as if we were just doing a query but two things on that note so first this code isn't super complex so even though it's technically going to be slower than if we weren't using this technically it's not really going to be an issue and secondly in a few lectures we're actually going to implement a really nice event system which means this code will only run when the units are selected or deselected and not on every single update so performance on this system isn't really going to be an issue and this is also a great example of how when working with dots technically you want to take as much advantage of the massive speed UPS as possible you want to really only access components in the memory that is tightly packed but in some cases like this you always need some kind of random memory access that's normal it would be pretty much impossible to make a game that completely avoids any kind of random memory access so while it is something you should avoid as much as possible it is also fine to use in certain scenarios okay so like I said this one should be cycling through it and should be making the visuals visible let's say to make sure let's save this and here in the editor let's make them essentially deselect by default so let's go inside of this prefab let's double click go inside on the selected and let's set the scale to zero so that it's essentially hidden or deselect by default okay great now let's test and Y right now by default none of them is showing the select visual now if I were to select a unit and over there manually let's select it and by the way if you make something as I enable but you add some extra logic inside of it some extra data if you do that then it no longer shows up over here on the tag section if so then it shows up as a normal component but it still has this nice toggle so right now the unit is not selected and if I click and if there you go the select visual did show up if I select a different one and set this one as also selected let's go down select and if there go now both them have the select visual all right awesome except one issue if I now deselect this unit so let's deselect it and move and okay so it is not moving but the visual is still there it is not hiding so over here for hiding it's actually super simple we can do pretty much a very similar query so let's copy this and paste it up here except instead of just looking for components that have the selected enabled instead let's use with disabled and we're going to look for the select component as disabled so this one is going to run on all units that are selected and this one on all units that are deselected and for the show scale let's just put it on zero to make it deselected okay that's really it super simple let's save okay let's test and by default all of them are deselected none of them are selectable okay great now I select one of these and let's manually make it selected so down here on the selected enable this and if there you go that one is now selected now let's Des selected and if there you go the vision appears and I can no longer give orders so I can select this one set it as selected select another one set it as also selected now I have both them control they both have visual deselect this one and only that one has a visual all right awesome with this we can now easily select any entities we want the visual updates to show whether they are either selected or deselected and depending on whether they are selected or deselected we can give them different orders okay great so with this we have our basic unit selection working except we are manually selecting them by clicking over here on the inspector we should really Implement some logic by selecting them by using the mouse in game so let's do that in the next lecture hello and welcome I'm your codem in this lecture we're going to set up the UI and learn how to create a selection area so that we can finally select multiple units all right so our selected logic is working we can only control units that have the selected enable so if I select one of them I can manually assign as selected it shows Visual and I can control just that one but of course we don't want to select the units by clicking on the inspector we won't do it directly in game so let's set up the logic for selecting units using the mouse and we're going to set up a standard RTS multi select mechanic meaning click on one place let go on another it creates a selection area and then we want to select all the units within that area Okay so over here on the unit selection manager in order to check if the player is actively selecting an area for that let's just listen to the left Mouse button down and up so here let's do an if input. get mouse button down on the zero so the left Mouse button and same thing for the get mouse button up also for the zero okay just like this and again like I mentioned previously we can later refactor this to work with the input system okay so we have the mouse button down and up now to get the selection area we basically just need to store the position on Mouse down and on Mouse up and then do some math to find the actual area so let's define a field to store a private let's make it a vector 2 because screen position only has X and Y let's call it the selection start Mouse position so we have this one and then when we press press on Mouse button down let's set it to input. Mouse position this is going to contain the mouse screen position that's exactly what we want we want this one and not the mouse run position nope we want the screen position okay great then on end let's do the same thing Define a vector through for the selection and mouse position and same thing input. Mouse position okay so now let's test let's do a quick log so do a debug. log and say up and showcase this one and up here let's say down and show the other one okay yep like this let's test okay so the logic is going to be on screen coordinates and based on the screen up here near this lower left corner it should be around zero and on the top right corner it should be around 1080p so let's see that so let's click over here and if it is down 37 so that is pretty close to zero now I'm going to go all the way up there let go and yep 1,900 by 1,000 yep pretty much 1080p so wherever I click it does match perfectly click let go and it does pick the correct size okay so far so good our basically logic is working so we know when the player presses when they let go and we know the positions of those so with that now let's set up the UI so in the hierarchy outside of the subscene let's right click we're going to go into the UI and let's construct a brand new canvas now I'm going to set it up like I normally do with all of my games so for the random mode yep let's leave it on overlay so this s correct then over here on the canvas scaler let's swap it from Conant Pickel size let's go with scale with screen size and over here for the reference resolution I like putting it on 10 AP so 1920 1080 and over here fully match with the height okay Yep this is the setup that I normally use so with this let's see what this does so let's right click on top of the canvas let's construct a brand new UI image and if there it is there's the image just like that so with this setup basically this means that UI elements will scale if the vertical size of the window changes so if I make this window smaller yep there you go you can see the white square that one is scaling up or down depending on the size however this will not scale if the horizontal size changes so like this with this and if I swap po it out to free aspect to make it really wide swap it and yep there you go everything still stays with the exact same size so this is how I normally set up the UI in my games that way I just need to make sure it all fits on the squarest possible resolution so something like 5x4 if everything fits over here then it's going to fit on pretty much any resolution and if the vertical size is smaller it's just going to automatically scale okay so that's really it we have our correct UI setup now inside the canvas let's get rid of this image let's right click let's create a brand new game object call this the unit selection manager UI on the re transform let's make sure to make it occupy the entire window so you want to select this one to stretch but let's also press on alt so that it modifies both the position as well as the width and height so hold down alt and click over here and if there you go it should be stretching with everything on zeros okay great now inside this one let's make an image so let's right click construct a brand new image let's name this the selection area image for this one we want to Anchor it on the lower left corner want to enter we want to Anchor and also modify the pivot so now we want to hold down shift so hold down shift and click on the lower left corner and Y there you go over here the pivot should be like this the anchor should be like this everything like this okay right this is really important if you don't anchor it on the lower left corner it is going to look weird and then finally for the visual over here for the image let's go with a nice scen so something like this and then just make it a little bit transparent so something like this okay great so our UI visually set up now let's set up the script to run this so on the project files again let's keep things organized so let's right click on the scripts folder just make another folder call it the UI and now inside of it let's construct a brand new monab Behavior script again another thing about dots versus game objects when working with UI you probably want to use normal game objects normal mod behaviors so let's call this the unit selection manager UI okay let's select the object let's attach a script and open okay so now here the first thing that we want is to store a reference to our visual as always let's keep our code nice and clean since we are not working with dots we are not working with a data oriented design because that over here we should be using good clean code objectoriented principles so let's define as private for a Rec transform let's define the selection area W transform and to make this exposed in the editor let's keep it private and make it a serialized field like this again since this is an intermediate course I'm assuming you already know about this attribute and why I'm doing this if not I have a video on this topic basically you want to limit access as much as possible so you should not make your fils public if you do you're going to enable read and write access from anywhere in your entire codebase that is not a good thing you should avoid it so you should default to making it private but if you make it private it does not show up in the editor so to solve that we add this attribute it keeps the field private so no other class can modify this field but by having this attribute it is going to be exposed in the editor so over here let's make sure to save now here in the editor wait for to compile and let's make sure to drag this reference okay so far so good now we want to update the vision based on logic and again let's keep our code nice and clean by keeping this UI class as decoupled as possible from the main logic class you should always keep your systems as decoupled as possible especially when it comes to UI you generally want the UI class to depend on the logic class but not the other way around technically your game should work just fine without any UI at all doing that will help you quite a lot in managing complexity so we're going to set up that connection between the logic class and UI class we're going to do that using events so over here back to the unit selection manager script let's fire off some events that the UI can hook on to so let's define a public event of type event handler this is the standard C event that exists inside system okay let's call this one on selection area start and let's make another one this is on selection area n okay we have these two events now let's just fire them so over here when we start let's invoke this event so question mark invoke with this an event ARS empty and same thing for this one when we let go on selection area end invoke it with this invent ARS that empty okay so far so good then of course we need UI class in order to be able to listen these events for getting the reference to this object technically we could make another serialized field or over here on this one we can just make it as a Singleton let's do that just in case we also need to access the script from other scripts so making a singon super simple so public static of type unit selection manager let's call it instance make the save property with a public get and a private set so y there's our Singleton and to set it let's make the standard private void awake one awake set the instance equals this okay great we have our Singleton and now back over here in our unit selection manager UI on this one let's listen to that one on start so private void start over here we can access the unit selection manager access the static instance and we can start listenting these events basically for this my general rule is you should use a wake for initializing each particular script and then whenever you want to access an external reference like over here on the UI we are accessing a different class for this make sure you do it on start just by following that super simple rule that is going to help you avoid a ton of code timing issues so here let's listen to this event so plus equals let's give it a proper name so the unit selection manager on start and same thing for the on end on selection end listen with the unit selection manager like this and there you go we have both them let's just do a quick log just to verify that this is indeed working so with this one let's print out this one okay like this let's save everything and now let's test so here we are and now left click and if there you go there's the down and the event was fired and I let go and yep there you go the other event okay great now let's set up the visual first we actually want to show it on start so let's actually put this one up here makes a little bit more sense so on start we want to show it and on end we want to hide it for that it's actually super simple like the simplest way to show or hide is really just enabling or disabling the game object so let's X the game object set active this one we want to show so set it to true this one want to hide so set it to false okay great very simple also by default let's start with it hidden so over here on start let's also hide it okay that handles the show and hide now for the size and the position let's go over here on the logic class and on this one let's basically make a function to calculate the current selection area so let's go down here make a nice function let's make it public since we're going to access it from the UI let's call it get selection area wct and for this function we're going to use a super useful data structure that is the wct that exists inside Unity engine this one represents a rectangle which is exactly what we want so this is absolutely perfect let's do this and over here we're going to return a brand new rect this one takes in an X and Y that is going to be the lower left position then a width and a height so for this we really just need to calculate the lower left corner and the upper right corner now initially you might think to just use this position right away the selection start you might think this one is going to match up as the lower left corner but that is not necessarily correct the player might indeed click on the lower left and let go above but they might do the opposite they might start clicking above and let go below so the start point is not necessarily going to be the lower left corner thankfully that's a super easy thing to do let's define a vector two for the lower left corner for this one let's construct brand new Vector 2 and over here on the X we can simply use meth f. Min this one Returns the minimum between two values we can grab the selection area start grab the minimum of that X and then for the end we need to grab it over there so let's grab the current end the current M position go inside this one X grab the minimum and same thing for the Y so grab the minimum of both y's yep that is going to give us the lower left corner and let's do the same thing for the upper right corner so the upper right corner except instead of the minimum we just using maximum okay great that's it so now with this we can easily construct our rect so for the X that is going to be the lower left co. X then for the Y lower left c.y then for the width we can simply go upper right corner grab the X subtract the lower left corner. X that is going to give us the width and same thing for the height except just using Dy all right that's it some pretty simple logic to calculate the exact selection area so now with this we can go back over here on the Y script and let's make a function that is going to update the visual so private void let's call it update visual on this one let's grab the re so let's access the unit selection manager the instance get the selection are rect so that returns aere for the selection area wct and with this Rec this has actually become super easy to use let's just go selection area grab the rec transform and we just set the anchored position we set it to a new Vector 2 and it's going to have the selection a.x selection a.y so this is going to be the lower left corner and again this is why it's so important that you anchor it the pivots correctly it has to be on the lower left corner so that way when we modify the anchored position it is going to be positioned on the lower left corner and finally we just need to modify selection area Rec transform modify the size Delta and for the size let's do another Vector two going to go selection area rect grab the width selection. height just like this okay yep that's really it so now let's just call this function so when we start let's go ahead and update the visual right away and then we need to update it as long as the visual is visible so up here let's make a private void update and on update if the selection area is visible which we can actually use just the game object if this one do active self if that one is active if it is visible if so then update the visual okay yep that's it so basically we just need to calate direct use it in order to display the correct size on the selection and then use events to show and hide so y let's save both files Let's test okay here we are and starts off is hidden okay great now I click over here and I move over here yep and it does show perfectly the square let go here and yep does work do the opposite starting above going down and yep does work so we can start clicking from anywhere and stop anywhere and everything works perfectly all right awesome again if yours is not behaving exactly as intended if so the first thing you should do is select the area image and make sure the anchors are set correctly it should be anchored on the lower left corner and the pivot also on the lower left corner and on the parent object this one should also be set to stretch to occupy everything so it should be set up exactly like this and in the code make sure you are doing this math all correctly if you do all of that then yep all of this should be working right okay so far so good our visual selection logic is all working perfectly we can perfectly draw exactly the square we want to select all that's left is actually selecting the units underneath so for that basically we need to figure out which units exist within this area and which ones are outside of it and there's actually one interesting point on this one when I was first researching this topic for the protab on this course instead of using screen positions like we saw instead of that I initially used World positions so instead of storing the start screen position I was storing the start worm position and then the end worm position however since the camera has perspective that did not work if you use screen positions and you click over here and then click over here if so then it is going to select this area however if you use wor positions and you click over there and you click over there if so then it's actually going to end up with a selection area kind of like this so it is going to end up with a skewed rectangle depending on the field of view on the camera is going to be more or less sked so the proper way is like this using screen positions and now we can finally figure out which units are within these screen positions and the way we do that is actually quite simple we just need to cyle through all the units the units have a certain worm position we convert that worm position into a screen position and then simply see is it within this screen position area so let's do that so back over here on the unit selection manager script over here when we let go in the mouse we need to figure out which units are inside it so let's just get rid of these testing logs we no longer need those okay so now let's do a query looking for our units so we're going to do something very similar to what we have here so let's actually copy paste this code so we grab the N manager from default World yep same thing then we create a new n query and now for the events over here here instead of unit mover we're going to need a local transform we're going to need that so that we have the worm position which we can then convert and then we don't want to select units that are already selected we want to cycle through every single unit so let's get rid of that one and just keep the local transform but again you might be seeing this might be an issue all the entities that have some kind of transform they are going to have this one whereas the goal is obviously to only select units so now is probably the time when we should create some kind of tag component to Define what exactly is a unit otherwise local transform is going to include anything even environmental objects so let's make a tag component for units let's just make sure this code compiles so let's just comment out this for a little bit okay let's save now here let's make our new mono Behavior so inside the authoring let's construct and again if you want you can use this pre-made Baker script but personally I prefer building it from scratch so let's do that call this one the unit authoring and over here the simple thing so let's make a public struct call it unit this is going to be I component data and for now it's really just going to be an empty tag component so yeah all we need is the baker to be able to add it so a class Baker let's Implement Baker with unit authoring so the usual standard thing then over here let's implement the abstract class we need to grab our entity so get entity get it to a transform. dynamic okay and finally add component on this entity let's add new unit component okay that's it let's save and over here let's select the unit prefab again select the prefab not an individual unit and on the prefab let's add the unit authoring okay great so now back in our unit selection manager over here we have our query so we can look for things that have a local transform and then also a unit component that way we make sure that they are actually going through units however enemies are also going to be units but they're not going to be selectable so we want to also include the selected component within this query but if we just do selected if so this is only going to query for entities that are already selected that is not what we want we want to be able to select units that are deselected so instead of including it in the query over here instead let's use one of the options let's use this one with present this one means that the component has to exist regardless of being enabled or disable so let's do this with presentence of the selected component okay great just like this so now let's construct our arrays so we're going to have an NTI array yep that makes sense but not a unit mover instead we want the local transform so let's name this the local transform array two component that array of a local transform okay now let's cycle through that array so cycle through the local transform array and now here we do something let's grab the local transform for this unit so the unit local transform go inside the local transform array on this index now within this unit local transform within it we have a position this is going to be the world position so now the goal is to convert it from a worm position onto a screen position and for that we can access the camera so camera. main to find our main camera and we can use the function world to screen point which does exactly that so let's pass in our world position and this one is going to convert into a unit screen position okay so we have the screen position of the unit and now we can very easily test is this position inside the selection area now thankfully the actual Rec type this one already has a function perfect for that so we can just go up here let's call the function and inside we have a contains function test if this one contains the unit screen position and if it does contain then the unit is indeed inside Al by the way over here since we are sing through an if let's make sure we cache our selection area there's no point in doing this all the time so here rect for the selection area rect let's call the function and then over here we just use it okay great so basically this means that unit is inside the selection area now this one we just want to select the unit so that is going to be super simple we just access the entity manager and then there's a function called set component enable we want to set the selected component we want to select on this entity so let's access the anti array on this index and in this case we want set it to true and yep that's really it so we cyle through all the these we do our query they need to have a local transform in a unit and they need to have a select component then we cyle through all of them we grab the local transform we use the worm position we convert that worm position into a screen position and with that screen position we test if it is inside the selection area and if it is we set the select component as true okay so that's really it this should be working the only thing remaining is we need to deselect the units we're really just going to deselect all of them and then only select the ones that are inside so doing that is quite simple let's just do a query for all units that are already selected so let's do another query before this one and on this first query we're going to look for things that are already selected so just selected no need for WID presence so just like this a super simple query then we just convert them into an in Array and then we cycle through that array so for in I through the N array. length second through it go through the N manager and set the component enabled for the S component on this entity so on the entity array on this index and set it to deselect and down here let's just reuse that one okay yep that's really it so we deselect all of them go through the selection area and select the ones that are inside of it okay so that's it let's save and now let's test okay here we are and first the visual still works okay let's try selecting one of these and there you go it did select it select all of those now select these and there you go did select select that one and yep there you go it does work so I can select all of these all these and everything gets selected perfectly all right Awesome by the way here our code has a slight bug so right now playing it this one does work perfectly so I can click anywhere drag it and yep it does generate the exact perfect square however this one is only working perfectly if you have the game scene over here set up exactly to full HD if you switch to any of these other ones for example if you put it on free aspect and now if we try and no it no longer works it's off both on the starting point as well as the entire scale the logic still works so if I click and drag here the visual doesn't work but the logic does work I can select the units but the visual is definitely a b off now this actually has to do with the scaler so if we select the canvas over here we set up the scaler and we set it up scale with screen size with a reference resolution of 1080p so with this if the game window over here is set up exactly on 1080p if so then it perfectly matches the canvas scalar so the canvas itself doesn't have any scale we can see over here the scale is on 111 however if we set it to anything else even if it is for example 16 by9 which keeps the same aspect ratio but lowers the resolution with this yep now that does scale the canvas and this is exactly what is causing that issue so we need to incorporate this scale in our logic now thankfully that's actually pretty easy to do we just need to take whatever position and scale we have and just divide it by this value so over here on the code let's just add a reference to our canvas so let's add a new serialized field of a canvas and here in unity let's just drag the direct canvas reference okay great and then over here the code is going to be super simple so it's over here on the update visual like I said we just need to divide by that value so we can grab the canvas let's access the canvas transform and grab the local scale and from this let's just grab the X all three of them X Y and Z those are going to be scaled EX the same amount so we can just grab any of them so let's grab the X and say this the canvas scale we get this and then we just need to divide these two by that so here divide by the canvas scale and this one as well okay yep that's it this should now work so here we are first of all on full HD and if I click and move yep it does work and now if I swap it out to free aspect ratio and move and yep now it still does work so I can put it on any aspect ratio anything we want like 5x4 and yep it does work put it on 16 by9 with scale and over there the canvas is inde the scale and everything does work perfect all right Awesome by the way I only notice this bug thanks to feedback from a student so if you do find anything not quite right in any of the lectures definitely let me know about it so I can fix it so the selection is working and of course the move logic that one is also still working so now we can select we can Define which units we want to move give them orders and everything works perfectly okay great so here we set up unit selection we also set up the UI and we created the logic for creating a selection area and actually selecting the units with this we can select any number ofit units and then give them some orders however there's actually one annoying thing here if we want to select just one unit if I click nope it doesn't really work we need to draw a square even if it is a tiny Square in order to finally be able to select the unit so just by clicking doesn't work need to do at least a tiny square that occupies the origin and if it does occupy the origin then it does select the unit now this is a bit annoying we should be able to just do a simple click and select an individual unit doing that is relatively simple but also means we need to learn about dots phys queries which is actually going to be a lot of fun so let's Implement that in the next lecture hello and welcome I'm your cod in this lecture we're going to handle the logic for selecting just one unit and the way we're going to do that is with a rast if it hits a unit and we select just that one unit so this means that we're going to need to learn about how to do physics queries using dots okay so we already have the selection area working I can select a bunch of units do a little square and select all the units within that area then I can just give them orders something like that however we cannot easily just select just one so I click on this one nope doesn't work I need to do at least a slight Square in order to be able to select so let's all this let's use physics and a recast to test for single unit selection now physics and dots is actually surprisingly easy to use but before that first let's add some logic to test when should we use physics meaning how to define when the player is trying to select just one unit versus selecting multiple for that essentially we can check the size of the selection area so if the selection area is at least decent size if so we're going to engage the select multiple mode but if it is small like something this tiny if so then we're going to select just one single unit okay so let's have that logic now first let's deselect all of them okay that makes sense so we handle all of the deselection and then for selecting let's grab the selection area W and from that one let's calculate a selection area size so float selection area size and for the size let's just use selection are rect let's grab the width and add the selection are re. height now technically this isn't going to be an area if it was an area we would do multiply it as opposed to plus but we're not actually trying to get a specific number we're just trying to get something and if we multiply we end up with a huge number so either way it works but let's go like this just have a simpler test so let's define a float for the multiple selection size minimum let's say something like 40 units we need to test this and basically let's find find a bullan for is multiple selection and basically we're going to be doing multiple selection if the selection area size if this size is bigger than the multiple selection size men if it is bigger than that then we are going to do a multiple selection and if it is smaller then we select just one unit so let's just do a log on this one so debug. log let's print out the multiple selection and let's also print out the current size just so we can see if the value 40 if this one does work right okay let's save okay so now here let's look at the log so basically if I do a big one like this it should select multiple so yep that is true and has a size of a thousand okay and if I make something like this this should probably be something like this should be the smallest so let's see how big is this Square that's about 100 so if it is something like this about 50 so yeah 40 pretty much means just a tiny tiny Square so as long as it's a little bit bigger than this then we're going to select multiple if it's smaller than this we're going to select just one okay so I think either 40 your 50 that one seems pretty good okay great so if I just click that is going to be pretty much zero select one if I do a square then select M okay good so now we have this simple volum so if we are doing multiple select then we're going to do this multiple select logic and if not then single select okay sounds good now over here let's learn how to do a recast so for that the first thing we need to do is grab something known as a physics World Singleton that is an external type physics World Singleton this one this type which exists inside unity. physics so up here let's go ahead make sure to include that okay so we need to access this type and this exists inside an entity so the way we're going to find that is by doing a query to get that type now for that we can do the exact same thing that we did up here create a new query Builder with all we would write this type and then simply get it that would work perfectly fine but let me also take this time to show you a different way of also creating an inti query so this way works fine using an inti query Builder that works but another alternative approach is to go through the entity manager so we go through this one and on this one it has a function called create entity query so now this one has a different syntax so instead of taking in the types as generics instead we write the type directly as a parameter and this one takes in an actual type object meaning it is not just physics World Singleton it is not just like this this is a synx error we need to pass in the type so let's use the type of keyword in order to convert that into a type so yep just like this so this is doing essentially let's copy this one just see the exact same thing so create new anti query Builder with all of the physics World Singleton just like this and build the query so basically both these lines are doing the exact same thing so feel free to use which one you prefer most okay so this one will return an entity query and that query is going to contain entities that have the physics World Singleton and like the name implies this one being a Singleton means there's really only one of them so technically we could take this query and do the same thing that we were doing up here convert it to an anti array or to a component that array of this type we could do that and then simply access the component that is on position zero that would work that would get us the component since again this one is only going to have one but the anti query this one also has some helpful functions like one called get single which does exactly that so we call get Singleton this one takes generics of a physics World Singleton just like this and Y this going to return an object of type physics worldl Singleton so that's it so we construct the query looking for this object and then this one automatically finds the single instance the single entity that has this component and we get it over here so with this we have the physics World Singleton and now inside of that one there is something called a collision world let's store this one so a collision world like this and and now it's inside of this type if we go inside Dot and Y here you can already see we have functions for doing a box cast we can cast some collator cast array check the sphere we've got a bunch of overlaps overlap sphere capsule and so on so basically this is where you can do all kinds of physics queries we're going to use these quite a lot now for this one for the click for this we want a simple raycast so we can just use this one over here cast Ray let's see what parameters this requires it takes in something of type raycast input so let's construct this type so Ray cast input construct a new Ray cast input okay and now for that inside of this one this one has a start that's a full three so it's a world position it has an end which is another FL three and then has a filter so for getting the start in the end that is actually quite simple again we are trying to do a rast from the camera's position so like we did on the script for finding the mouse R position so over here on this script we use the camera in order to convert a screen position onto a ray and then from this Ray we can call get point to get a point on any position within that Ray so over here in our code we can do exactly that so let's grab AR aray for the camera array so here we go inside the camera get the main and let's call the function screen point2 Ray this one takes a screen position and converts it into array so for the screen position let's use input. Mouse position okay yep that's it however here we actually see an error it is saying Ray is an ambiguous reference between unity. physics. rray and unity engine array basically the unity engine array this is one for the game object world and unity physic physics this one is from dots physics both of those name spaces contain a ray class so one solution is to go up here and get rid of one of these we could get rid of the UN engine but then we would have errors whenever we use debug. log so down here let's just write the full name so this one screen Point array this one is going to return the unity engine. Ray so let's write the full name so Unity engine. Ray just like this so we have the camera array and then from there we can call the function get point this one takes in a distance and basically Returns the point at that distance along the ray so for the start point we want to start pretty much at the camera position so let's start on zerf and then for the end point let's do the same thing and basically we just need a point that is far enough away now technically we could do a ray cast in order to find the perfect distance that the unit is from the camera position or you can just simply put a huge number either one is really going to work fine so up here let's just put a bunch of nines and that is more than enough to actually collide with the unit so do that and the final parameter is a filter this one is of type Collision filter this is a special dots type let's construct a brand new one a new Collision filter which by itself also has three parameters it has belongs to collides with and the group index now these are essentially layers or rather layer masks so the ray is going to belong to this layer and it's going to collide with this layer the layers over here are the ones that you define on the game object itself so if you go back over here into Unity let's select actually our prefab instead of any of these okay select the prefab and over there on the inspector we can see the layer drop down menu so we can click on it and we can add some more layers so for example over here for layer six for the first empty one let's define this one as our units layer so just write units now here we just need to memorize this number so this is going to be in layer six and now we can select the prefab again again select the prefab not the ones on the scene and on this one let's swap this one from the default layer onto the units layer and nope we do not want to apply to Children the only thing that matters is the object that has the col which is going to be this one so let's go ahead yep okay so this one is now on the units layer which again is layer number six so here in the code for the find that that is exactly what these are going to represent we use those layers to say that this rcast is going to belong to a certain layer and it's going to collide with a certain layer and by the way for the group Index this is basically a special override this one is just a number you can see it's just an INT so if you put a number here like number 56 and then you have another object that has the exact same group then the raycast will always collide with that object regardless if it belongs to a different layer or does not collide with that layer so basically the group index is always going to be an override but in most case we don't really need to worry about this one so we can just default this to zero like that okay so now for these two that are important they belongs to and collides with so how exactly do we set these up this one is actually a uint so an unsigned int but this one is a bit mass number meaning that layers are defined by the digit position in binary so over here we do not put six this is not correct like I said this is a bit mask number so a bit mask means that essentially the layers are going to be defined by the digit position in binary so here we have an 8bit number defined it has 8 Bits all of them them are on zeros so if we were to use this as the belongs to layer then the ray cast would not belong to any layer because again everything is on zero so if we want to hit layer zero then we need to flip this bit so we need to flip this from zero onto a one and Yep this would be the layer mask for hitting things on layer zero and if we wanted to hit things on layer five so this layer zero 1 2 3 4 and five so we want to modify this one and we would flip this bit into a one then if we want to hit both layer zero and five if so we just put both them on ones so this is a bit mask basically the layers instead of being integers they are essentially just positions on a bit mask those are zero or one depending on what layers you have selected for either the belongs to or the collides with so over here as to how exactly do we construct that bit mask we start with number one which going back to our diagram here one is really just this so a bunch of zeros with one at the end so we start with number one and then we bit shift so put two angled brackets this called the bit shift in this case we want to bit shift to the left by the number of our layer so if we wanted to shift this to the left by three then we do it just like this so essentially what we're doing is first we Define a one and then we take this one and we essentially want to move it to the left so move to the left by one position two positions and three positions so yep that logic is doing exactly this it is finally generating this number so here in the code if the goal is to collide with everything on layer six if so then we need to do this and we do not do this that is a completely different thing so let's do one bit shift by six however we also should not put the six here you shouldn't really hardcode magic numbers like this magic numbers are always something you should avoid magic numbers is really just a number that has some special hidden meaning that is hard to decipher so in this case right now we just wrote this code so we know that this six means the units layer but if we leave it like this we are definitely going to forget what it means so instead of hardcoding a magic number let's use a properly named local variable so up here just to find an in for the units layer say six and then over here in our code do it like this yep now this makes quite a bit more sense except we also see that we have an interesting error this telling us we cannot implicitly convert from in to uint that is because the belongs to this one is a uint it is not an INT so this one is a simple solution we take this one instead of using a one which is an INT let's append the word u and if there you go now this one is assigned as a uint okay great so this is how we construct a bit mask and actually for this one we want this rast to belong to every layer and collide with that one so let's actually Swap this so let's put this one like this we want to rast to collide with only things on the units layer and over here for the belongs to layer simplest thing is to really just make it belong to every single layer the collision at the end the rast will be whatever matches both these so to make the ray cast belong to all layers that is also pretty simple we start with number zero which again going back to this diagram the number zero is literally everything on zeros so all the bits are zero in order to get all the bits into one we really just need to invert them and the way we do that is with a tiled so that one essentially takes all these zeros and convert them all into ones meaning that rast will belong to every single layer and again this one should be a u so let's opin U just like this okay so yep that's it and just another quick mention that you might not know about that relates to over here the belongs to and collides with as to why this has both of these instead of just having the collides with for that here in unity we can actually go into edit and let's go into project settings then on the left side let's go into physics the physics settings and Y over here we see what is called the layer Collision Matrix here you can Define that some layers do or do not interact with some other layers so that is why over here the ray cast has that option so you can make it belong to a certain layer and only collide with certain layers okay great so here is our rast input so we Define the start point that is going to be the point directly in front the camera the end point is going to be a near infinite distance falling along the Ray and for the filter we're going to make this raycast belong to every single layer and make sure it only collides with the units layer and the group Index this one is just default okay great so like this now we can use this Ray cast input on the cast Ray and now for the other parameters so here we have multiple versions of this function so you've got this one which will out put a Rak has hit this will output just a single closest hit or we have this version this one returns a native list which is going to be a list containing every single hit that gets hit along this line now in this case we really only want to select a single unit so let's just grab the closest unit so let's define an out raycast hit for the raycast hit and again Ray cast hit exists in both the physics engine for the game objects and dots so let's be explicit this one we want the dots so unity. physics. R asset okay yep so here is our correct array now this function will return true if it has something and false if nothing is H so let's do this into an if so if this raycast if it has something if so then we want to look inside the raycast hit and over here we can see the entity so we can find out which entity did we hit now technically since we made sure that it only hits things on the units layer because that we can be pretty sure that this one is going to be a unit but still if we want we can just ask the entity manager to verify so we can for example go entity manager inside that one we can check has component and we check does it have a unit component and yep so if this entity has that component then hit a unit okay and that's really it so now we can just go into the nty manager call set component enabled set the selected component on this entity so Rayas it. entity set this one into true and Yep this should be working so as you can see it is really simple to do a physics quaring dots you just have to set up data for the rast or the overlap sphere or whatever and you just call function and of course before that the more complex part of just having to go through all this we need to construct n query we need to get the physics World Singleton and then get the Collision War so it's a little bit more worthy than the normal game object physics where you just do physics dot overlap box and so on so doing it in dots is slightly more complex but still it is pretty understandable just grab the physics World Singleton get the Collision world and from there you can do all kinds of physics queries okay so let's test and see if all this is working let's make sure to save okay so here we are those are all the units um just going to try to select just this one so just a click and Y there you go it does select just that one unit now select all of them move them all it works single click select single click select and so on so I can select individual units or I can select all of them and tell them where to move all right awesome now it looks a bit odd that all the units are moving into the same place on the next lecture we are going to generate the proper move positions so let's reenable justy Collision just to see what that problem is actually going to solve so over here let's just go inside the unit prefab and on the caps Le let's make it not a trigger so let's make it so that it's solid and yep it is playing they all go into the same place and they all hit one another so they no longer go on the exact same position and now I can select can move a bunch of these and yep everything does work okay great everything works but of course selecting multiple units and clicking still looks odd because again they are constantly trying to go into just one position they're constantly pushing each other around so instead of telling them all to go to the exact same position instead of that we should write some simple code to generate some valid Target move positions so let's do examply that on the next lecture hello and welcome I'm your kod Mony in this lecture we're going to learn how to dynamically generate some move positions so our units don't all try to go to the exact same spot okay so right now we have units that we can control I can click the select select an individual one select the group and all of it works however right now all the units those are all trying to go to the exact same position which leads to all this spelling up they get all kinds of collisions looks really strange basically the more unit we have the worst is going to get now there are actually many ways to solve this problem so one way is to sort of leave it like this and then simply make the unit stop moving when it gets to the Target and then allow it to be pushed around so that's one option that could work but another option that I think is best is to generate some proper move positions so just like in many RTS games you have formations that's basically what we're going to build here we're going to dynamically generate some positions in the code and send each unit to a slightly different position now there are many shapes we can generate so RTS games usually have some kind kind of rectangle formation sometimes they have Circle formations you might see some Arrow formations and so on so you can really go as simple or as complex as you want in this case let's go with a very simple Circle formation so we're basically going to have our Target position right down the center and then we are going to generate rings around that exact same position and on each of those Rings we are then going to generate a bunch of positions within that ring and the further we go out in the Rings the more positions we can generate so by following this logic even if we have just one unit or 10 units or 100 units everything won't work we're basically going to slice a ring into as many times as we need we're going to basically slice the ring into how many positions we want to have so in this case let's say we make a slice here then make another one here make another one here and another one here way we do that is first we start with the vector pointing right so we have this vector and then we're basically just going to add some rotation onto it so we have this Vector this going to be the first position on this ring then we're going to rotate this Vector down here that is going to have this Vector pointing down down here and that is going to be our second position then once again rotate the vector down here and gives us that position so we do that and then for the second ring we really just use a bigger Vector just going a little bit bigger and same thing we still rotate and so on okay that's the rough logic now let's implement it so over here on the unit selection manager script let's make a function to generate our positions so let's write private and for the return type technically we could return a normal Vector 3 array we could return this that would work but instead let's actually return a native array make it a native array of FL 3es again native array that is a native collection that works with dots and burst so let's make this one and call it generate move position array then for the parameters so first we need to know the target position so 4 three for the Target position and then we're also going to need to know how many positions do we want to generate so an INT for the position count okay sounds good so now here the first thing we do is create the array with this size so native array of type flow 3 that's going to be our position array let's construct a brand new new one let's use allocator temp to make it temporary and for the size let's define with the size of position count okay yep just like this then we can simply test if we are requesting zero position so if position count equals zero if so then we don't really generate anything so let's just return the position array if not then let's keep going so if we're generating at least one position then the very first position on the array so on index zero this one is going to be the taret position we always want to make sure that we want to use that position and then let's do another if so if the position count if it is one then this one is really all we need so let's return the position array okay and if not then let's finally generate all the other ones so first let's define some settings so we basically need to define the ring size so how far away is each ring from the origin so let's find a float for the ring size and let's use number like 2.2 okay then we also need to keep track of which ring we are currently generating so let's define a ring int for zero and let's also keep track of which position index we are trying to assign now since we already assigned the origin over there on index zero let's start with the position index and start off as one okay great so now here we're going to run our generation logic while the position index while that one is under the total position count so basically keep generating until we have all of them so that makes it perfect to use a while so while the position index while that one is under the position count while doing that then we're going to generate a bunch of positions so it's over here that we want to cycle through all the Rings and calculate all the positions first thing we should Define here is how many positions we're going to have for this ring as ring expands we can see it has more area so as it expands we want to have more positions so we don't want it to just be fixed we don't want to have just four positions on every single ring we want to have some kind of minimum and then some kind of bonus depending on the ring so let's def find an NT for the ring position count is how many positions we want to have in this ring let's find a minimum of something like three and then add let's say ring times two so on the first ring on ring of zero we are only going to have three positions then on the second ring ring of one it's going to have 3 plus two on next ring it is going to have 3 + 4 and so on okay so now that we know how many positions we want to generate for this ring let's actually go through them so let's cycle through all those positions let's use a simple for so and I starting on zero while I is under the rank position count i++ okay we cycling through all the rank positions and now here like I said we're going to have a vector we're going to start with a vector pointing in some direction and then we're basically going to apply some rotation then keep increasing that angle until we have all the positions generated so let's calculate what is this angle which the first one should be an angle of zero we should just get the vector then for this one should be some kind of angle and so on so for colting the angle it will be whatever is the index of the angle so are we trying to get on position index zero 1 2 3 and so on we're going to take that and basically for calculating this angle we just need to divide the entire rotation divided by the number of positions we want to have on this ring okay so here for calculating the float angle for this one let's take once again start with the index and then multiplied by the angle which is going to be the entire ring split by some amount of ring positions so let's grab math. Pi 2 pi 2 this one is the entire ring again this is all in Radiance and we divide this by the ring position count so if this one gives us the angle that we want to apply for this one and now with this we can calculate our ring position so what is going to be this ring position so it is going to be the target position plus we take our Vector pointing to the right so that is going to be a new Flo three and for the size of this Vector it is going to be based on the index for the ring multiplied by the distance so that is going to be the ring mul multiped by the ring size except for the first one we also want it to be offset if we use a ring of zero then it's just going to spawn in there no we want to spawn in here so over here let's use ring size multiplied by and then use the ring plus one just make sure that even on ring zero we still offset by the ring size and yep we just want the vector pointing right so just like this so this is the vector and then we just need to apply a rotation to that Vector so actually Define up here a FL three for the ring vector and we're going to start off with this one like here and for the rotation we can use math and call the rotate function this one takes in a Quan and a flow three vector and simply applies that rotation so now we just need to take this angle which is in radians and convert into a quion so for that we can use Quan and call the function rotate y because we are working on a top down so we want to rotate on the Y angle and rotate by this angle and use this quion and that Vector okay so yep so this is the ring vector and we just apply that outset onto that one and yeah that's really it so we start off with a vector pointing straight right we apply some rotation to it and then we take that final Vector apply to the Target position and that's how we get our ring position so again going back to diagram here we have this Vector pointing right then we apply some rotation and we get this ring position and since we are doing this inside of four and inside of well this logic is going to generate every single grid position so now that we have our ring position all we have to do is add it down to the native array so let's just access it on the position index and assign to this ring position we assign it and then let's make sure to increase increase the index like this and after generating one position we can see is this last position so let's test if the position index it is bigger or equal to the position count if so then we have generated all of them so let's just do a break to get out of this for Loop because we don't need to generate any more ring positions so that breaks out and ends up down here whilst inside of the well and at the end of the well what we need to do is make sure to increase the ring index so we go onto the next ring and of course if we have generated all of them this going to be false and we're finally going to exit the well and then over here we just return the complely filmed position array all right yep that's it so this was a bit of math but I hope it was understandable again we generate some rings outside of it calculate a VOR apply a rotation and doing that we generate as many ring positions as we want this function can work with one position 10 positions 100 positions everything works great so the function is going to return a native array so now up here in our code we just need to use it so let's go over here onto the right Mouse button so this is where we are giving the units the orders to move so after we get the entities and the unit mover let's call down for the Target position that is going to be the mous wor position so this is going to be our origin and for the position count we can go for example grab the anti- array graval length and Y so this one is going to return a native array of FL three this is going to be the move position array and since this one is going to have the exact same size as all these arrays then over here when assigning the target position for this specific unit let's go inside that array on this index like this so yep that should be correct just like this all the units each unit should be going to a different position so let's make sure to save and try it out okay so here let's select just one unit tell to move and Y just a single unit still goes towards the target position okay so far so good now let's select a bunch more units and right click and let's see and if they do go to different positions and we can see a sort of ring forming so there's the unit down the center and all these three over there let's select all of them tell them all to move and see where they go and up like this we can see the second ring coming around so as they all move around they all go to different position they all generate and whether it be with one unit or multiple units they all go to different positions this code works with five units 10 units 100 units everything works right all right awesome now the only thing is the units are still pushing each other around especially if we move through them they're trying to push things around now later on we're going to solve this with some basic collision avoidance and of course later on we're also going to implement pathf finding so instead of the units going straight they are going to follow the path and avoid obstacles right now they just move straight with no concept of walls or anything so we're going to implement all of that later on but for now this is looking good we generate the move positions tell them to move and they all go towards the target position okay so our logic is working our game is really starting to take shape we can select any number of units give them orders tell them to go here you go here and everything works so now it's time to learn one very crucial thing events specifically how to handle events in dots which is actually a very interesting topic so let's do that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn one way for how we can handle events in dots meaning how to know that something happened in a specific frame one way we're going to use this is to make sure that our visual selection logic only actually updates when it needs to update okay so here let's learn how to do dots events events are one of my favorite Tools in programming in my games I use events a ton to keep my code nice and clean and minimize code coupling as much as possible with normal C events you can keep one class completely decoupled from the other one usually the main way that I use them is separate the UI code and the logic class like we already saw in this course this way the UI class is tightly coupled to theic class since it does need to have that reference but theic class this one is completely decoupled from the UI class it does not know that any UI class exists anywhere does not know and does not care this is really awesome and helps you quite a lot in managing code complexity the more decoupled your code is the better it is so events are awesome however since dots is data oriented that means events are actually quite tricky to do usually when working with an event you access some kind of object reference then you listen to that event and the event itself is a delegate which is another object so in dots we're not working with objects so we can't use delegates or references or anything like that instead we need to figure out some way of doing a data oriented events now this was actually really tricky for me to figure out how to do events without objects I tried doing some research but couldn't find much on the topic of data oriented events so I'm not 100% sure if my Approach is the best one possible but it does work quite nicely so let's see it since we cannot have objects and attach listeners events instead let's define a component and that component is have a bunch of bulls then we are simply going to turn those bullions into true whenever some event happens and then at the end of frame we're going to raise all of those bions then if we want to essentially listen to event we just need to play some system to read the state of these bullion right before the reset system okay so for storing the bullion let's store what it actually makes sense first let's s the events for when the unit is selected or deselected so for that makes sense to put it here on the selected component so we've got the visual entity the show scale and over here let's add some Bowlings for events so let's make a simple bow one for on selected and another one for on deselected okay great we have our two nice events now to quote unquote fire these events let's go here on unit selection manager where we are selecting our units let's scroll down to find where exactly we are deselecting all the units so over here let's also get a component for all of our selected so entity query let's go into query get the component data array do it of type selected with allocated temp okay so this is going to return our native array of type selected and over here let's do the logic for grabbing and updating it so let's do the same logic that we had previously this one that we did over here where we get the array we update data and then we call this in order to updated so let's go up here and do exactly that so let's go inside the select array on this index let's grab the select so we grab the selected then go inside the selected and this is the D selection logic so let's set on the selected equal equals true then again let's update the component inside the array so select and equals this and finally go into the ant query and let's copy copy from component. array and let's copy in the selected array okay that's it just like this however actually this event is going to throw a really interesting error so let's see what it is let's make sure to save it save this one and also make sure to save the select authoring save all the files then let's wait for it to compile and now let's see that error so here we are and it's working fine if and if I just click anywhere empty so click and like go so here we are and everything is fine let's select some units okay works now when I click here to the select let's see and if there it is there we have our error so here in the console the error is saying length of the input array is a size of eight and does not match the length of the query which now has a size of zero now this is a really interesting error it actually took me quite a bit to figure out what exactly was happening here basically this code over here copy from component. array this one is trying to update eight positions that's how many positions we have over here on the S array but the anti query this query is now matching with zero units and this is because over here we are sing through the entities and we are setting the selected into false by doing that we are modifying how many units are actually selected so when we then access this to do this it is basally going to rerun this query and since we set the M as false after running all this logic then this anti query will no longer find any selected units so this is a really sneaky really tricky error always keep in mind when working with enable components if you disable them they will no longer be included in queries now thankfully the fix for this SE super easy we can just do it the slower way meaning let's get the component and update so let's get the selected set it to true and then instead of updating the array let's go entity manager and call set component data on this entity array on this index and let's update it with this select component and we do that instead of this okay that's it let's test okay here we are let's select a bunch of them it works deselect and yep it also works no more errors so I can select deselect select one deselect and yep everything works okay great right now for the selection logic let's go down to where we are selecting our units so here we are selecting multiple and selecting a single one so for example let's go over here on the selecting a single one this one is going to be super easy so on this one entity manager let's get the component data get the component data of type selected for the ray asset. entity so we want this entity selected so that's the selected like this and then we just update so in this case the unit is being selected so un selected set this one true and then again in manager let's set the component data on this Rak asset. entity and set it with this select okay so that is going to update the single unit and up here for updating multiple up here is where we can actually do the exact same thing we were doing a while ago then over here for the multiple selection let's do the exact same thing so we're going to get the entity in this case it's on the en array indexi get that one and update it with this one okay great so this should be working let's save and now let's test okay so everything is playing let's select one of the unit so let's select this unit over here and over here with the inspector on runtime mode Let's scroll down until we find our selected component yep there it is and right now the unit is not neither selected nor deselected so both events are set to false and now if I go ahead and select that unit yep there you go the unit is selected and the unselect event that one was indeed triggered and finally for deselect just click here and yep there you go it got deselected and theond deselected event did work all right awesome so here we can see that our events are indeed working when we select they get selected deselect we get deselected now the next step is to make it reset so let's build a system that will do that so let's go inside our systems let's create the new entities new I system call this the reset events system and now on this one let's keep just the update so just like this and here it's going to be super simple so we just want to cycle through all the events and set them all back into false so let's do a system api. query let to a query we're looking for the selected and we're going to want to modify it so ref are W for the select component so this is going to be our query so let's do a for each for each the ref RW on the select component called selected in this query except again remember we're working with nabl Mod components so if we do this and then we update the events over here if we do that it is only going to reset the events on the ones that are currently selected whereas we want to also reset the ones select event so instead of just including the ones that are just selecting instead let's head over here the option with present of the selected so this way anything that has a selected component will be included here so now we just go with the selected the value RW for reading and writing and set on selected into false and same thing for the on Des selected okay that's really it super simple super basic just like this the code won't work it won't reset events however it won't exactly work like we wanted to so like this this code is indeed going to cycle through every single slide component and we'll reset it but it is not necessarily going to do that at the end of frame so now is a great time to look at the systems window once again let's set on play and just see so here we have all our systems let's look inside the update the simulation system group we have all of our systems for example here is the select visual the UN mover and here we have the reset event system now the order in this list this one is very important so basically this system is going to run then this one and then this one so the code is going to run from top to bottom however note how this one is not at the end of the frame we got lucky that the event just by default happened after these two custom systems but could have happened just before this one I'm going to talk about how the system ordering is semi- random in a little bit but importantly is we can actually manually modify the order we can tell to update before or after any system in this case it's already running after all of our custom systems so the goal is to run at the end of the frame but just for testing let's say we want to run before the testing system so here in our system we can simply add an attribute and we can write update and we have two of them update before to run before a system or update after so in this case like I said we want to update before the testing system so let's use this one then this one takes a system. type meaning we have to write type of and then the system name so in this case the testing system okay yep like this let's see and Y there it is look at that it does work so now our reset event system is running before the testing system so with this we can easily update and set it to update before or after any kind of system and another thing we can do is look at these folders these are what are known as system groups so we can also tell our system to run within any of these folders for example like I said the goal is to run our reset event system at the end of the frame so we can place it over here inside this one inside the late simulation system group let's do exactly that so here in the code instead of the update before let's use another one let's just write update in group and same thing this one takes a type so let's write type of and we want the late simulation system group okay yep like this let's save and let's test and if there it is our reset event system that one is running inside the late simulation system group and with this we have indeed achieved our goal it is running at the very end of frame so we have the update this where we run most of our logic most of our systems are going to go next to these ones and by putting it on the late simulation it is always going to end up after all these default ones okay so far so good so we already have some code setting an event to true and then we have another one that is resetting the event to false at the end of frame so that's left is really just something to listen to that event in the middle now in this case our main goal is to update the visual when the unit is selected or deselected so let's go here onto the selected visual system right now this update is running all the time so on every single update it's cycling through all the entities that are selected or deselected and always updating transform that's pretty wasteful so let's make it only update when the state actually changes so for that let's make a different query so we're going to have a 4 in we're going to run through the selected except instead of with disable just with present we want to run through every single entity that has the select component and then over here we just check if selected. valo if the unit is selected if so then we're going to show if not then we're going to hide it so this one is the on the selected and on the unselected we are going to do this and if the events are false we're not going to do anything and over here we can avoid trying to get this so we only do that semi expensive call we only do this one if we actually modify the transform so that's it this is the code we can now get rid of these so with this it is still going to cycle through every entty that has a slide component but if the state does not change then it really just checks a bullion which is a super fast operation if nothing happens then it is not going to bother running this relatively expensive call neither to do this on the transform now let's just add some logs just to test that this is indeed working so let's do a debug. log except it is not the systems Diagnostics debug let's use the unity engine. debug okay and this one on selecting make sure this one only triggers exactly as intended and this one is the on D selected okay that's it let's test okay yep so this the logic now we technically have one potential issue here that may or may not happen but let's quickly test so here we are looking on the console and nothing is happening so just by default we can see that code is not running on every single update so if I click somewhere nope nothing happens or if I select one yeah there you go it did select that unit now I can tell it to move I can deselect and yep that one did work I can select a bunch of them yep unselected deselect unelected okay so that's great everything did work but while it did work on my PC but while it did work on my PC it might not have worked on yours that is because of over here the order in the systems that order is semi- random meaning it is not guaranteed to be the same across all PCS but for every PC it will always have the same order that is what I mean by semi- random so on my PC if I stop and I start playing again I'm going to get the exact same ordering for the systems on your PC the order might be different but it will also keep that order also note how what I'm saying here is related to the unity editor itself meaning if I were to make a build of the game right now anyone playing in the build would get this system order it does not change after building only during edit time so anyways my point is that the order the systems is not guaranteed it might or might not have the order that we want since on the select visual system we are listening to the event we need to make sure that this system runs before this system and the easiest way to make sure that happens and technically by default like I said by default systems will run over here so since we place this one on the light simulation Group by default we can assume that one is going to run before that one and since the unit selection manager since this is a mono Behavior it is not running on do srl that means that this logic over here that one is going to happen before any of that logic so technically over here we don't need to do anything technically this should work but still we should learn how to make it very specific to make this one run before this one in the future we are going to have other dot systems that also trigger some events and we need to make sure that whatever system is listening those events happens after they are triggered but before they are reset so over here on theelite visual system let's just make it run before the reset event system so up here let's use same thing so update before type of let's update before the reset event system okay just like this let's test and open put is actually not working here we can see an interesting warning it says ignoring invalid update before attribute on the select visual system targeting the reset event system the issue over here has to do with groups basically you can only modify the ordering you can only tell it to update before or after other systems that are within the same group so select visual system this one is just in the simulation system group but the reset event system that one is on that one so if we want to update this one relative to this one it has to be running on the same group so quite simply over here we can just add both attributes so we can add update in group on the type of on The Late simulation system group so we do that one make sure it updates in group and then make sure it updates before this one so yep this should work let's test and yep it does work so there we have the reset event system and over there we have the selected visual system and we can see on logic works I can select some of them and if visually does work it does update it does fire off the event and it only fires as many times as it should now deselect now select that one move that one and so on and yep everything is indeed working perfectly all right awesome so here we have our nice data oriented event system it does not use delets or objects or anything like that but still achieve the same goal we can have some systems do some logic just depending on some event and by the way let's get rid of these logs so this logic is only going to run when the system is triggered so this logic is only going to run when this event is triggered and the event is always going to be reset at the end of frame No Matter What by doing this we also end up with the same decoupling benefits meaning that for example over here on the unit selection manager over here when we set this event to true this script has no idea that something is listening to this event maybe it does maybe it doesn't it does not matter this one just sets the event to true on the reset event system the same thing this one does not care if anyone did anything with this event it just sets it to false in between we can have or not have something that listens to those events and does some logic in the end we end up with something that works select deselect and everything works perfect okay so here we Implement some really nice dots events our game is already looking quite nice but so far all we have are really just our own units it's finally time to add some enemies so let's do that in the next lecture hello and welcome I'm your KMI in this lecture we're going to learn how to finally create some enemies and Define them as actually being some enemies we're going to Define a simple infection system so that we can have Jessy player and enemies and maybe in the future we can add bunch bunch more factions okay so far we have our units we have the unit selection like you find in any RTS so I can select individually or select a bunch of them and everything does work but so far all we have are just these player units there's really nothing to fight against so let's do that now for that we have two options we can take this unit prefab and make the enemy prefab a completely separate prefab or we can make the enemy be a prefab variant of this in prefab in case you don't know prefab Varian is kind of like inheritance in C so you can have a base prefab then you can create a variant that extends that base and maybe overwrite some settings now since all our units are going to have quite a lot of similar components let's go with that approach of using prefab variants that way whenever we want to modify something to all units we just modify the base unit prefab and it applies the changes to both our fin units and our enemies okay so first let's actually rename this call this the base unit and now let's make a variant and the way we make a variant is right click directly on the prefab let's go into create and let's construct a new prefab variant let's call this the soldier unit this is going to be our friendly and let's make another variant and again right click on top of the base unit do not make a variant of the soldier unit nope make another variant of the base unit so right click let's create a new prefab variant let's call this the zombie unit okay so we have our three types now for the differences only the player Soldier only this one can be selected so we can get rid of the select authoring from the base unit and from the zombie unit so let's go on the base unit and on this one get rid of the select authoring and also let's go in inside the base unit so let's double click and over here since it doesn't have the selected it doesn't need this one so let's also get rid of this one but before we do let's actually copy so contrl C to copy it let's delete it and now let's go on the soldier unit this one should have the selected and yep let's save the base unit and on Soldier unit contrl + V and paste are selected and Y like this all the settings should be already set up correctly so the soldier has the selected mesh and let's also make sure that the soldier has the selected authoring component again not the base unit just the soldier and this one let's drag the select reference and put the show scale like it was on two just like this so like this it should be correct let's go back out and save it so on the base unit this one does not have the selected so it has the unit mover yep all units are going to move we've got the rigid body caps col and unit authoring then on the zombie unit it has exactly those same things and on the soldier unit it has those things plus an override of an extra selected authoring component so next let's set up the zombie unit so let's go inside the pream and over here really let's just modify the mesh so for the mesh instead of using the soldier a mesh let's use the zombie wonk mesh yep that's the zombie wonk mesh just need to modify also the material instead of the soldier let's go with the zombie material and Y there it is there's our zombie and so far we don't need to modify anything else here then let's make it a little bit slower just because zombies should be slower so let's put a move speed of three okay like this let's save the prefab go back outside of it and now let's just set up these ones over here on the world so let's actually get rid of all these so delete them because those were the base unit we do not want to actually use the base unit we just want to use the prefab variants so over here let's drag a soldier unit drag it directly on top of the subscene again make sure you put it on the sub scene so that it gets converted into an entity and now yep there's our soldier and let's make a bunch more so a couple more soldiers like this okay we have a bunch of soldiers and let's also drag a zombie unit again drag it onto the subscene and put the zombie over there and yep that should do it let's do a quick test make sure everything is still working so yep here we are playing and yep all of them are indeed working so the soldiers and I can also select them I can move them around I can select them individually or select multiple and yep everything does work and on the zombie if I try nope it does not work I cannot select which is exactly what we want okay great so far everything is working correctly so now let's make the actual enemy zombies so for that the first thing is how do we exactly do we Define that something is an enemy zombie or rather we're eventually going to have multiple unit types both for the player and multiple zombie types so how do we Define what is a player unit and what is a zombie unit how do we Define what exactly is the concept of a faction or a team so the simplest answer the simplest way to implement that is using a simple enum so with that then we have another question where exactly do we Define and store that faction enum now we could make a component to just store the faction that could work but in our case the concept of a faction is relatively simple and all units will belong to some faction all units and all buildings so instead of a dedicated component we can store the faction over here in the unit authoring component although for defining it other things might also belong to a faction like I said buildings so we want to have a field to Define our faction inside the unit authoring component but then we want to define the faction itself on a separate file so let's do that and this file isn't going to be a mon Behavior or authoring or system or anything so let's just make it over here on the scripts folder create a brand new mon Behavior script let's call it faction and then over here we can get rid of all of this we're just going to define a public enum call it faction like this and for our two factions let's have friendly and okay yep that's it a super simple enum this is the easiest way to define functions so let's go ahead and save this and then on the unit authoring component over here on this one let's just add a simple faction field okay there's our faction and let's make sure to expose it on the othering component so the same faction and when we add a component let's add the faction go into the authoring and grab the faction okay yep this should do it let's save and over here back in unity let's go to our prefabs again there's no point in modifying the base unit let's just modify these two so on the soldier unit let's go ahead make this one a friendly and actually like this it is going to inherit the one from base unit so technically we can live it like this or we can actually Force this to be an override force it to always be friendly even if we accidentally modify the base unit we shouldn't really modify the base unit but still let's make sure this one is actually an override and the way you do that is you really just force some change so change to zombie yep now this one is bold meaning this one is an override and now we can get back to Friendly and yep now it has the override and the over right is being overridden as friendly okay so that's the soldier and for the zombie unit let's change from faction into zombie okay that should work so now anytime we want to check what faction a unit belongs to we can simply grab the unit component and inside check the faction although sometimes it can also be useful to very easily look for friendlies or zombies it might be useful to find certain objects through queries instead of having to cycle through every single unit and then check the data inside of this unit component so in order to make it easier to query for for friendlies or enemies for that on top of this let's also make some simple tag components for our factions so on the other ring let's right click construct a new mod Behavior script for the friendly authoring and over here this going to be a super simple tag component so just a public struct call it just friendly let's Implement I component data just like this no fields and then the baker so class Baker Baker of friendly authoring and we implement the baker script then over here let's grab the entity to get as always let's default it to Dynamic and then add component on this entity a new friendly component okay yep super simple now let's also make the zombie authoring so let's right click on the authoring create the new monab Behavior script for the zombie authoring on this one let's do the exact same thing so a public struct call it zombie I component data simple tag component and finally a baker class Baker of zombie authoring let's implement this one and over here as usual get the entity equals our get entity let's add the component on this entity a new zombie component okay that's it let's save here let's go on the soldier unit and on this one let's add the friendly authoring yep okay this one will have the tag and on the zombie unit let's add the zombie authoring okay so like this both of our prefabs should be correctly set up let's do a quick test so let's go over here on our testing system and over here let's do basically the same test that we had previously for the unit count let's count the units except instead of this quering let's just look for units with the friendly component so just put friendly just like this friendly and we don't need any of these so let's get rid of all that just friendly like this without the WID present just like this okay so let's see how many friendlies are within our scene okay it's saying seven and let's see so we've got 1 2 3 4 5 6 7 yep that is correct and now let's swap it out for the zombie to check out the zombie tag let's see and if this work we do have just one zombie all right awesome okay so here we created the concept of a faction we also set up our prefabs and variants very correctly so that we can very easily have different types of objects this is going to be super useful when later on WE Implement all kinds of different unit types however so far we still have no interaction between our soldiers and the zombie they really just exist in the world so let's handle Logic for finding our Targets in the next lecture hello and welcome I'm your codm in this lecture we're going to implement the logic for finding a Target Target then after we find that Target later on in future lectures we can actually shoot that Target okay so here we have all of our friendly units we have the friendly ones that we can easily control and over here we have a zombie so both types both factions already exist but so far they are not interacting with one another so let's Implement some nice combat now for combat before we actually do some kind of damage the first thing we really need to handle is how do we find Targets so how does this unit know that this zombie is close enough to be attacked let's first handle that finding a target for this unit for that let's make a simple F Target system so inside our systems let's right click create go inside entities a new I system let's call it find Target system and also for this system we're going to need some data for the settings on how exactly we're going to find the target like for example what is going to be our find Target distance and so on so let's make a component to handle that data so on the authoring let's go create new mon Behavior script find Target authoring okay now with this authoring component let's attach it to the base unit so let's let our base unit scroll down and let's drag the F Target authoring component it's very important that we attach the base unit because all of our units are going to be able to find Targets we want the soldiers to find Targets and also want the zombies to also find Targets okay so let's make our find Target authoring component for now let's make it just a simple empty component so struct find Target I component data and for now let's leave it just like that let's just do the baker class so as usual let's get the entity get entity let's make this a dynamic entity and then add component on this entity a new find Target component okay so far so good we have our simple find Target component now let's go over here onto theine Target system we don't need the uncreate so let's just keep our on update and now on this one let's think what exactly does finding a Target mean it means cycling through our units all the units that have a fine targeting component those are the ones that should be looking for targets we cyle through all of those and for each of those units for each of those entities we are going to be looking for units that are nearby and then also validating if it's a Target so soldiers should only target zombies and zombies should only target soldiers so over here let's do our query so system API let's do a query now for finding a Target we're eventually going to check the target distance so we're going to need the local transform and this one we probably only need to read it so let's make it a ref R local transform then all the settings those are all set up on the fine Target component so let's also grab that one also ref just read for theine Target component and if with that we should have our correct query so let's just finalize this so make the function add the for each for each ref R let's pass in the local transform call it local transform then another one for the ref R fine Target call it fine Target and let's also organize this make this nice like this and the system. query let's add some new lines just to make it nice and clear just like this okay great so we have our query we grab the UN local transform let's just put this like this the local transform and theine Target okay great and now for actually finding the objects for finding things that are nearby near this unit for that we are going to be using a physics quaring so we already saw how we did rast over here on the unit selection manager we already use a physics query in order to do a recast so to do that first we grab the physics World Singleton then grab the Collision world and then call a function on it so in our find Target system let's do exactly the same thing first we need the physics world and over here since we are inside a system we can use the super helpful system API which by itself already has an excellent get Singleton function so this makes it super easy to get the first Singleton so that's the physics World Singleton let's grab this one okay we have the physics World Singleton and then inside of it we want to grab the Collision World okay up like this by the way it's important that I'm doing this outside of the four each just so we don't waste any performance we don't need to constantly grab this so let's grab it just once and then cycle through all the units okay so now here let's go inside the Collision world and the perfect one for finding units that are nearby the perfect one in this case is doing an overlap sphere this one will basically give us all the entities within a certain sphere area so let's see the parameters for this one it takes in a starting position so for the position that's going to be the position for this entity so let's grab the local transform. value Ro o. position okay then for the radius this essentially going to be the range so for this let's make a field on the fine Target component so let's go on Define Target and over here let's add that public float call it range personally I prefer the word range as opposed to radius I think makes a little bit more sense especially in the context of finding a Target so okay so here we have that and and let's just pass it in find target range equals authoring that range okay so now this one we can use that so find Target let's read it read range okay next one we have is a native list of distance hit this is going to be the list of all the entities that this overlap sphere is going to hit and once again let's be smart about it instead of constructing a brand new list for every single for each instead of that let's construct just list once and then reset it for every entity so here let's make a native list of type distance hit so distance hit list let's construct a brand new one and this one as usual let's make it temp so it gets automatically deallocated at the end of frame okay so we have the list we're going to use this one and also importantly over here note how this has the ref keyword so we need to make sure to include this so ref for our distance set list and since this one is going to basically be reusing the list let's make sure to clear it before we actually fill it up okay great and for our final one finally we have the Collision filter once again this like we already saw let's do it so it only hits units so you can do literally the same thing that we did over here on the unit selection manager just construct a new Collision filter that belongs to all units and only collides with the units layer so technically we could just copy paste this code however we should really not have multiple separate references to our units layer that way if we modify it we would have to modify it in tons of different places this one should really only exist in one place we should not have any duplicated copy paste code so let's make a general class just to handle data like this and before we create a new file let's just save these so over here on this one let's comment out just so it compiles and save this one as well so save both these files okay let it compile and let's create a new one so we're going to construct a new mon behaviors so let's go inside mono behaviors let's right click construct a new mono Behavior script and this time let's call it game assets this is the name that I personally really like for this class basically this class is going to hold all kinds of assets and references and this one is a normal mon Behavior so let's create a game object with the exact same name again create the object outside of the subscene let's call it game assets let's drag the game assets component reset transform and open okay so now in this class we want to be easily accessible from anywhere usually the purpose of this class is to be an easily accessible Library so that we can have with all the references that we need so usually I like making this into a Singleton however technically in this case we don't really need this to be a single ton but still let's do it just to be ready for the future so let's make the usual singl ton logic so public static of typ game assets call it instance let's make with a public yet and a private set and then on the private void awake we just set the instance equals this okay there's our static Singleton instance and another the reason why I said it doesn't need to be a Singleton right now is because we're going to make the units layer a constant and constants do not require an instance but still this way this class is nicely prepared for the future so here let's define a public constant for the units layer in this case we have unit layer six okay great so now we have some data here so back first over here on the unit selection manager over here let's refactor this code instead of using this local variable in instead of that let's go inside the game assets and access the units layer yep so now we can copy this code go into the fine Target system and on this one let's define the Collision filter like this and we do use the game Mas as unit layer so in case we want to modify the layer we really just need to go into this class and modify this and everything else will work okay so let's in comment this and we can now include the Collision filter on the last one on this one and if that should do it so now this will return true if it finds anything and if it finds anything if if it finds at least one entity if so then the results will be populated in this list so let's check if it is true that means there is something within this area and if so then we basically just need to validate these entities again keep in mind how here we are looking for the units layer meaning this will actually collide with both friendly and enemy units so we need to validate if they are a valid Target over here let's cycle through all of those so for each of type distance hit distance hit in the distance hit list okay we cyle through that enti list and now for validating if it is a valid Target for that we're going to define a valid Target essentially being the faction of the unit that we are cycling through here is an enemy of the unit that we are cycling through here so that means we need to Define what is the target faction so let's go on the find Target authoring component and over here on this one let's make a public faction call it the target faction and let's pass it into the baker so Target faction authoring Target faction so now back in Define Target system over here we can now use it so we can have Define Target and within that we can read and find the target faction so now we just need to know if this unit over here if this one does belong to the faction that is the target faction if so then it is a valid Target so we just need to know the faction of this one so for that let's go inside the system API let's get the component get component of type unit that's where we were storing our faction and we want for distance hit. entity so we want to grab the unit for this one so unit this going to be the target unit and then just check if Target unit. fact if it does match the target faction that we have in our F Target component if so then this is a valid Target and if if it is then we want to set this as our Target now let's just do a quick test just make sure all this is working so here let's do a debug. log debug. log on the distance hit. entity and just make sure that and here we have the usual error for some reason Visual Studio is importing system. Diagnostics instead of unity engine okay so we have that d. log and up here let's just do a dash just so we can see which one is finding that way we can see this message and then this message okay so let's save everything make sure to save all the files which by the way the shortcut is control shift s and it saves all of them okay great so now here let's wait for the compile and we need to set up some components so let's go into our base unit and on this one let's scroll down and this one just needs to have the component okay great now let's select the soldier unit on this one for the find Target component let's find Targets within a range of some like seven units and this one we want to Target the zombie units okay and then for the zombie unit let's put the target range a bit smaller let's say just five and this one does want to Target friendly units okay so let's see if like this if our logs are indeed working let's test and okay so by default we're just seeing a bunch of dashes so none of the units are finding any enemy but as I move this unit closer at some point this one should find the Target and if there you go it does work so one of those is indeed finding a Target and it is finding Target entity 182 let's see if that's a zombie unit and yep there it is zombie unit is indeed 182 and if we get close enough to where the zombie also finds that one as a Target so let's go a little bit closer and if there it is it does work so the zombie unit is finding 179 and if we select this unit and if there is Soldier unit 179 all right awesome so our logic over here is indeed working now we just need to figure out how are we going to store this Target and the answer is Let's Make a component just to store the target we want to make a separate component as opposed to putting it inside the fin Target just because other things are going to have different methods of finding a Target so let's have a component just to define a Target let's go in our scripts on the authoring right click construct a new mon Behavior script call it Target authoring and if this one is actually going to be super simple let's make a public struct call it Target I component data and for this one all we want is have a Target and let's make it of type entity so that's the target entity and then let's make a baker so public class Baker Baker of type Target authoring however this one is going to be basically just an empty Baker so let's Implement that one we do not have any data that we want to pass in from the authoring component onto the target this one is just going to be set dynamically so up here let's just get the entity entity equals our get entity and let's set a component on this entity a new Target component yep just like this we do not pass in anything okay let's save back over here let's set the target onto the base unit so that all units have a Target so here let's wrag the target authoring okay great and now we can go over here on the find Target system and when we have a valid Target let's just sign the target so on our query let's set another one we want to write to it so let's put a ref RW of type Target and let's add it over here on the query so ref RW Target Target okay so now down here we set the target grab the value bar W to WR and the target entity will be distance set. entity okay yep like this let's get rid of these logs so like this it should already be working like we saw the target logic that one is already working so now we should be able to see the target being assigned on the target component so yep let's save okay here we are let's select just the first unit okay there's the soldier I believe it is this one yep it is moving over there on local transform so it is this one okay great now let's scroll down find Target component okay let's see the target component and if there it is and right now it has none it has no Target and as I move a little bit closer as I get Clos enough there you go the zombie unit now is the Target and if we select the zombie unit and now we look let let's find the target component there it is so far no Target and as I move a little bit closer and if there you go it does find the soldier unit as the target all right awesome so everything is working perfectly the soldier finds the zombie as a valid Target and the zombie finds the soldier as a valid Target and of course this working for all these so if I get all of these way too close if so and I inspect any of them pretty much all of them are going to have down here on target yep they do have the zombie as a Target okay so our fine Target logic is working great although let me point out just one small thing here as you might see we are doing a 4 each cycling through all the distance hit and I do not believe that this one is going to be ordered by distance from the target meaning I don't think that as we go through this for each the first one is going to be the closest one so technically if we want to find exactly the closest Target if so we need to add some extal logic here to make sure that the Target that we select is indeed the closest but for now this is working more than fine enough as soon as we find one target let's break out of the four each and so far this should be working okay great so the fine Target logic is working our units are finding targets soldiers find enemies and enemies find soldiers let's just add one more tiny thing over here to this logic basically one of the best tips that I can give you on performance one of the best tips related to either dots or game object doesn't matter it's a great General performance tip so that tip is simply run logic less often than on every update now here after we Implement jobs and burst after we do that this code will actually be insanely fast so technically we don't necessarily need it but still we also don't really need to check for a Target on every single update the units move relatively slow so there's no point in looking for a Target 60 times per second so let's add one of my favorite things a simple flow timer let's do that to make sure we only find Targets a few times a second and not on every single update that is a super simple thing so let's go on the find Target component and over here let's just add two floats so let's define a public float for the timer and another public float for the timer Max and for these two really the only one we need to set is the timer Max the timer will set at zero and then increase automatically ly so let's just make the timer Max and set timer Max authoring that timer Max okay great and now over here on the fine Target before we do any of this complex logic before that let's just go inside the find Target grab the value R for reading let's grab the timer and we check if the timer is above zero so if this timer is above zero f if so then basically timer not elapsed meaning we do not want to find the target so over here let's basically short circuit this so let's just do continue to continue onto the next entity but of course before this test let's actually count down the timer so since we're going to modify it we need ref RW on Define Target so let's modify this to ref RW okay let's go and Define Target value r w so we can write timer minus equal system API time. Delta time okay we count on timer then we check if it is laps if it is not laps then we just continue we ignore this entity but if not let's restart the timer so find target. Val RW let's set the timer equals find Target now let's just re value R and gravity timer Max so that's it and over here let's add a log just to verify debug. log find Target just make sure this one is not being called 60 times per second so let's save this save both files and now we just need to assign the timer Max so over here let's select the base unit scroll down to the find Target and for the timer Max over here let's put it on 3F meaning it is only going to look for targets once every 3 seconds so y let's play and see the logs okay there it is and right they found the Target and now they are not finding and now they found again and now they are waiting and a little bit yep find some more and so on all right awesome so our simple timer logic is working perfectly so let's put now a more proper number so something like 02 so basically it's going to find a Target five times per second which I feel is more than enough okay great so now that we can find Targets the next step is to actually attack them our soldiers those are going to be using bullets they're going to be shooting them so we need a system to handle that and then we also need a component to store some data so let's do the same thing that we did for Define Target let's first make a component to store some data so create new mon Behavior script let's call it shoot attack authoring however here we have an interesting thing not all units are going to shoot like our soldiers they are going to shoot they have a weapon but the zombies they are only melee so in this case we do not want to attach this component onto the base unit that would make it so that every single unit can shoot nope we just want on the soldier so on the soldier let's scroll down and let's drag the shoot attack authoring okay great now here on the script let's make the standard components so public struct shoot attack this an i component data okay great and let's make the standard Baker so public class Baker Baker shoot attack authoring let's implement this Baker get the entity entity get entity entity Dynamic add component on this entity a new shoot attack okay great now let's think what that do we need well the first thing is we do not want to shoot a bullet on every single update so we need some timing logic so let's do the same thing that we just did for theine Target make a float for a timer and a public float for a timer Max and the only one we need to pass through is just the timer Max so let's pass through this one go inside the shoot attack open and close this one equals authoring tammax okay like this let's save okay so here let's see the soldier units scroll down find the shoot attack Yep this one and let's put it on like point2 so it's going to shoot five bullets per second which should be a nice amount okay okay so that's the data now let's make a system to handle our shooting so on our systems folder let's right click let's construct a new entities I system call this the shoot attack system and now here on this one we want to cycle through all the entities that have both a Target and a shoot attack so let's do that first clear up these ones and on the on update we're going to want to do a system api. query query for everything with a shoot attack and we want to update the timer so let's do it a ref RW for the shoot attack and then for for the Target itself let's make it ref we're just going to read The Target just our Target component okay let's put this inside a for each for each ref RW of our shoot attack call it shoot attack and also for the ref for the Target and simply call it Target let's just format this nice like this and put this one and this one like this close the parentheses open and close okay great so now we're secondly through all the entities that have a shoot attack and a Target however all the soldiers are going to have this target component but that ises not mean they actually have a Target so the first thing we need to do is check if the target actually exists so for that we can do an if let's go inside the target let's read the target empty and we can basically compare this against a nice constant so let's see if the target does not equal and the constant entity. null this one represents a null entity so essentially represents that we have no target selected so here let's actually put if it is null if it is null then we want to skip this so continue if it is not null then we continue doing something so down here let's first count down the timer so the usual thing that we just did a while ago so let's grab the timer minus equals let's go system api. time. time and then if the shoot attack let's read it let's read the timer if the timer is still above zero then not un lapse so let's continue and if it isn't then shoot attack let's grab the value r w for writing and set the timer equals the shoot attack let's read it value r o and grab the timer Max okay so that's that's it so now down here is where we actually spawn some bullets deal some damage something like that we're actually going to spawn the bullets in a little bit in order for those bullets to deal some damage we also need to implement an actual Health System but for now let's just do a quick test just to make sure this is working so debug. log and once again this implemented system. diagnos that is not what we want so let's do using Unity engine so do a debug. log and say just shoot okay let's see if this log does show up and over here on theine target system let's just get rid of this log okay so let's test okay so here we are and no one is finding targets no one is shooting so now this one as this one approaches it should find the Target and then should start shooting and if there you go shoot five times per second all right awesome okay so here we added the logic for being able to find the targets so our entities look for units around it and Define if that unit is a valid Target if so then it assigns it as a Target and actually only notice that we have a bug with our select visual right now so the bug is if I select all of these sounds good now if I select the exact same units now it looks like like they are deselecting but if I move yep they are still selecting so it's a very simple bug it's over here on the select visual system basically if we select the units twice if so then both these vents are going to be true at the second time and if both are true then it's first going to select and then it's going to deselect so the super simple solution is just swap the order so first handle deselection and then if the unit is both deselected and selected on the same frame if so then it will have the visual so if that's it let's save let's test so now here if I select a bunch of units and now select them again and if there you go now they do always show up and selected very correctly okay great and another bug that I also just noticed right now is if we click to select the zombie yep we have this error basically the error is over here on the unit selection manager where we have the logic for selecting just a single unit where this one does the castray and so on then checks if it has a unit component and then automatically assumes if it has a unit component then it can be selected whereas that's not the case the zombie is a unit but is not selectable so up here let's just set another and entity manager let's check if it has component and let's check if it has the selected component so rast hit. entity so this way it is only going to select if it's a unit and is a selectable unit so yep let's save Let's test okay here we are and if I click on the zombie and Y there you go no more bugs everything works great all right awesome okay so here we implement the logic for finding a Target so the units look for units that are nearby they identify if that unit is valid so if it is part of a Target faction and if so then they assign it as a Target so it works for both the soldiers as well as for the zombies and then the soldiers also have some shoot logic they check if the fine Target was successful if they did find a Target if so then they count on a timer and they start actually shooting the enemies so all that logic is working except we don't have any kind of concept of health so that means we need to build some kind of health system so let's build that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to implement a really nice Health System when the unit is Clos enough it will be shock and it won count down the health then when the health hits zero it will destroy that unit okay so we already built the Sho attack system so as this Soldier unit gets closed it will eventually find the Target and start shooting so as I move a little bit closer y there you go finds the Target and start shooting okay great so we already have this logic working perfectly all it really needs to do is just deal some damage so to Define some health let's make a health component so on the project let's go on the authoring right click construct a new mod Behavior call it health authoring now let's make this one a simple component so public struct call it health I component data and let's make the standard Baker so Baker Baker of the health authoring let's implement the baker function grab the entity entity get entity as Dynamic so the standard thing that we already did so many times add component on this entity a new health component okay yep just like this so now what that do we need for the health well the simplest thing is just some kind of Health amount so let's make it public and now it's up to you to Define what format you want to Define for the health some people like to use decimals so they like to use float personally I prefer using ins I think they look a little bit better let's call it health amount okay so we have the health amount and let's pass it in so up here for the health amount let's pass it in to our health component so this one equals authoring do Health amount okay so let's save this and now back into unit let's select our base unit prefab let's attach to this one so that both soldiers and zombies both of them have health so let's go ahead and drag the health authoring put it like this and for for now let's just default all of them to have 100 Health okay that's good now we can go back on the shoot attack system and over here where we are doing our shoot over here let's just deal damage to our Target so for that first we need to grab the health system of the Target now it's important it's the target it is not the one that we are cycling through here so if we have a soldier shooting a zombie over here we are cycling through the soldier entity but down here we want to deal damage to the zombie entity so let's first grab the health so let's go into the system API let's get components in this case we're going to want to modify the health of the entity so instead of using this one which just grabs the component instead let's use this one which actually returns a ref hard only that way we can then very easily modify the amount so this one let's grab of type health and for the entity let's go inside the target so the target for this one let's read the target for the Target entity and this one is going to return a refr w of type health for the Target health and now we can simply deal some damage so let's define n for some kind of damage amount and for now let's make it just one then let's go into the target Health grab def value our W for writing and the health amount just counted down by our damage amount okay so that should really do it that should already be damaging our zombie so let's save and let's do a quick test okay here we are and let's just select the zombie unit and let's inspect the health component so let's see where's the health if there it is we have the health amount of 100 okay now I take one of these soldiers and as I move them close enough they should start shooting and if there go the health of the zombie does start going down okay great so this working the health amount is counting down but let's see what happens when it hits zero and yep that's it the answer is nothing happens basically we need some way of handling unit death so one way we could handle it here so after here we can test is the health amount under zero if so destroy the unit or as always we can do it in a dedicated system both options can work in this case the better option is to use a dedicated system just so later on we can have more options for things that can deal damage so let's make a new system let's go into the systems folder right click a new entities eye system let's call it the health dead test system okay so now this one let's make our standard update like this now this one we need to do a query for all the health components so system api. query let's read the health so refr o of our health and that's probably the only one that we need so let's you just say for each ref r o on the health like this so the health okay we have just one component we cyle through on the health and then just check if the health value r o the health amount if that one is under or equal to zero if so so then this entity is dead so this is where we need to destroy this entity which means this is actually a great time to learn one thing which is how exactly do we get the entity reference here we are doing a query and we get the component of the query but we don't actually get whatever is the entity that this query that this component is attached to if we go inside the health nope we have no reference to any of that there's no reference to any entity even on the value rro we still have no reference to the entity so over here on the query we are just getting components and we can't really just write entity over here this do not work this is not valid code but thankfully it's actually pretty easy so after this we can cycle through all the various options that we already saw and one of them is called with entity access so we use this one and in doing so then we need to add another parameter over here on the first iterator so let's have the health and then we have an entity parameter let's just comment out and format this properly so let's put it like this and put the N with a query like this okay so yep like this it is working so basically by calling this you then have to add this entity field and importantly it needs to be at the end we cannot place this one in the beginning if I try putting that in the beginning and then the health afterwards nope this is not valid code so if you use with entity access you need to put the entity as the last parameter so like this okay great so with this we now have the ENT that we are cycling through now we can just simply destroy it and for destroying we need to access the ENT manager and while working inside a system over here note how we have this system State and if we access that state inside there we have the enti manager so that is the enti manager where this system is running and within that enti manager we can call the function destroy entity so like this takes an entity so let's destroy this entity okay yep that's really it however this will throw an error but let's try it anyways just to see let's save it so here we are let's select the zombie so we can see it let's inspect the heal of the zombie okay like that let's approach with a bunch of soldiers and they are close enough they are shooting and yep the health is counting down so let's see what happens when it gets all the way down to zero so there you go like that and yep we have have an error here it is it is saying structural changes are not allowed while iterating over entities and then it says here please use an entty command buffer inste so again the error is because destroying entities is what is known as a structal change I already talked about what those are a while ago I mentioned why we use an enable component for the selected instead of adding or removing components so here it's really the same thing except instead of modifying the components instead of adding or removing instead of that we are destroying an entity which again is also a structural change when we destroy an entity that means that dots on the back end has to reorganize all of the memory arrays they always all need to be tightly packed so if one enti is destroyed it needs to move all the other entities in memory now if we do that here inside the 4 in not only is it a costantly operation but it actually breaks our code in this case we cannot be cycling through something and then basically modify that collection now the solution here is actually quite simple we don't really need to destroy the entity immediately right here instead we can essentially queue it up for Destruction so we can do all our Health testing logic we can identify which enties should be destroyed and then after doing the four each afterwards then we can actually destroy those enties so the way we can queue up commands is with something known as an in command buffer that's basically a buffer for queuing up in commands and for using an in command buffer we have two options we can manually create a brand new one or we can choose one of the ones that already exist let's see both options so first let's see the manual one so up here before our for each let's construct a new entity command buffer for that we do new entity command command buffer just like this and this one as so many things takes an allocator so allocator and let's use the temp like we're used to let's just add the using statement for these up here so using unity. collections okay so we have the ENT command buffer so like this and then down here when this enti is dead instead of destroying it instantly through the enti manager instead let's just destroy it on the enti command buffer so up here let's call destroy entity and let's destroy the exact same entity again importantly this is not actually destroying the entity right here it is simply up that command and then down here after we exit the four each over here let's access our in command buffer and let's call playback and this one takes an N manager so let's PR in state. N manager and you like this it won't work so we construct new n command buffer we queue up some commands on that buffer and then we tell to playb back which essentially means that the entty is going to run all of these que up commands and it's going to execute them on this entity manager so this way we are no longer destroying entities in the middle of the 4 in we simply cue them up and and then destroy them all okay so let's save and let's test okay here we are let's approach the unit with all of these let's see the health amount going down okay it's all going down 60 50 going down to zero and yep it did work we did not have that error if we look in the 's hierarchy we can see yep the zombie unit is no longer existing so that's great that part worked but we did have a different error like it says here the N does not exist so we are trying to do something with an NTI that does not exist basically what happened is the NTI was destroyed but then we still try to to do some Logic on that destroyed entity that's why we have this error here and also by the way this is a great time to see something very important about debugging right now if we select this eror and we look down here we can see this AR log this Tech Trace looks very strange look at all of these very strange names for the functions for the class names the lines and so on all of this looks super strange and none of the links are clickable so for example over here I can see some error happened on the shoot attack system and usually you can click on this in order to go to the offending line but right now we can't we can't really see that this has to do with the fact that we are using burst now burst makes it super fast it applies tons of optimizations to your code which makes them insanely fast but at the same time the downside is that it makes it quite a bit hard to debug so if you're having trouble debugging something then the simplest option is really to just disable burst so let's stop playing let's go up top to jobs burst and let's not enable compilation okay let's play again and let's trigger the exact same thing get the all Clos enough to shoot and now let's wait for that unit to be destroyed and throw the error again here's the error again and yep now with burst being disabled now the errors are much more easily understandable they are easily understandable and now we can actually click on it so we can click and see the error was on the shoot attack system line 28 so let's go inside this one and it appear here is shoot attack system on line 28 so if you're having trouble debugging something just go ahead and disable burst also by the way remember to reenable burst after you saw that bug also here we can see another very interesting Quirk about how dots works like I said in the very beginning dots works very much based on Source generation meaning we write a bunch of this code and then dots the dots compiler is going to run through this code and going to add a bunch more things so in between you runting the code and the final compilation the code runs through a system which adds a ton more code onto your code that is why we have to mark this as partial so as to why that matters is over here in the code we can see the error is on the shoot attack system on line 28 but over here on line 28 we are just defining a local variable this line cannot possibly throw an error so the error is actually not on this line it's actually on this line over here so it's on line 27 not 28 now this is a little Quirk of dots that it's very important for you to know because of source generation the lines can look a little bit off so it might tell me that the a is on line 28 but it might be on 27 29 or any of the ones that are nearby so if you are confused keep in mind that the offending line might not exactly be the offending line so if you have some error and you don't know what exactly is causing it make sure you look at the lines nearby not just the exact one that is selling the a okay so anyways now that we've learned that let's actually solve this error so basically the problem is like I said is that the unit is still trying to attack an entity that no longer exists so basically as you cycle through multiple units that are shooting the same zombie eventually one of those units is going to destroy the zombie which then runs the he dat test system which is going to destroy that entity but then the next time this one runs the other entities that still have a target the target is not null it is simply pointing to a target of an entity that has since been destroyed so we basically need to validate the data that we have inside the T component and again we could write it directly here or we can make a dedicated system to do that so let's do that on these systems let's construct a brand new go into entities a new I system let's call it reset Target system and for this one let's cycle through everything that has a Target so doing a system API doing a query let's read and write on the target component so for each ref our W on the Target and call it Target okay we do that like this so we cycle through all the targets and then here we can just validate the targets so if Target let's grab the Val r o just for reading grabb the target entity and we can basically check does this entity still exist so the way we do that is we can go through the system API and call the function exists and check if this one does exist or not so if this one does not exist if the target has since been destroyed then let's simply reset it so let's target value RW set the target entity equals entity. null and if that's it this one will clear the Target now the only important thing is we need to make sure this one runs at the end of frame and actually I'm going to cover that specifically in a little bit after we see the alternate approach this anti command buffer but now let's just make it work so let's just write update in group so the same thing that we saw previously type of on the laay simulation system group okay like this let's save so here let's approach let's see if that one works let's see if the zombie gets destroyed and if it did work the NT was inde destroyed now it might not look like it but it was if you look over here on the nt's hierarchy we can see yep the zombie unit no longer exist however we still have bug which is the visual the visual mesh that one was not destroyed we're going to handle that in a little bit but the important thing right now is that we did destroy the main entity and it did not throw any errors okay so before we solve that visual bug let's just learn more about the an command buffer so here this code is working we made it work by using a custom created command n command buffer this works however another option which actually works best is to use one of the preset n command buffers if we start playing the game Let's pause and let's look over here in the systems window and if we scroll down we can see we have a bunch of anti- command buffer systems so there's one over here on the begin simulation and one over there on the end simulation basically we can reuse this one instead of creating a new custom n command buffer the benefit of this approach is basically to limit when you do structural changes as much as possible so right then a bunch of systems all doing structural changes in multiple places in the same frame instead of that we can all run all of those commands just at the end the frame so the way we do that is we access that n command buffer and that one only exists once so that is going to be a Singleton so let's go through system API call get Singleton and the type that we want is called n simulation anti command buffer system and now here an important thing it is not just like this nope we need to access through this one and access the Singleton that exists inside of this one so yep that gives us the Singleton and now within we can call the function create a command buffer and this one just takes in a parameter for an unmanaged world so for that we can access the one inside state. world unmanaged and if that's it so this will now give us an N command buffer so let's use that instead of creating that one so yep just like this we do this we queue up the commands as usual the the important thing is we do not manually call playback again like I said this one will run automatically at the end of the frame okay so just like this let's test so here we are and let's look over here on the anti Hy so we have the zombie unit and we have a bunch of soldiers they are attacking the zombie and the zombie is Health going down and if there we go The Entity was indeed destroyed and no more errors all right awesome and over here for the health de testing system let's also put it to update on the late system group all right now let's solve the issue with the visual here basically the parent object that one is being destroyed however the child object the one that contains the visual mesh that one is not being destroyed now this is actually a very strange bug that took me quite a lot of trial and error to figure out during my research basically it's a weird bug that only happens to units that are placed directly in the scene during baking if we were dynamically spawning this unit if so then this bug would not happen that is what took me quite a long time to figure out I will show in a little bit how this bug does not happen when we cover unit spawning but for now let's just solve it and thankfully the solution is quite simple we just need to go into our prefab and yep and over here we need to add a component and it's a component called linked entity group and yep that's it basically if you dynamically spawn a prefab it is automatically going to add this component onto it but if you don't dynamically spawn it then it doesn't add it so that is a very strange thing but just by adding this we should have the bug fixed so let's do another quick test and let's get the units closed enough to destroy and after a while we should be able to see the zombie and the visual mesh destroyed and if there it is it did work the zombie's gone and the visual mesh is also gone all right awesome so now everything is perfect here we constructed a brand new health system and added the logic for damaging and destroying the target Although our shoot logic isn't really shooting anything just now there are no visual bullets just an integer going down so let's add that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to create some BS we're going to create the bond object and the system it will basically move towards the Target and deal some damage okay so we already have the shooting logic working as the units get close they find the target they automatically find the zombie Target they start shooting and yep after a while the zombie takes some damage and gets destroyed so all the logic is working the health is working the fine Target is working the shooting is working all that works but right now there's no visual there's no actual bullet so let's do that first let's construct our object so on the subscene let's right click construct a new empty game object call this the bullet then inside let's make a child object let's make it a sphere and on this one on the inspector let's put it on authoring mode mod and let's get rid of the spherical leather so we just have a visual and for the visual itself let's go ahead and choose this bullet material see there it is just a nice material with a little bit of glow if you want you can increase a little bit so if you want you can go over here on the emission increase the intensity if you want to make it really glowy I think something like this looks pretty good and for the divisional size let's also make it a little bit smaller this is way too big let's put it maybe something like 44.5 something like this should be good okay great so that's our basic Bond setup again we we have an empty Parent Game object where we're going to Place El logic components and then a visual in a child object okay let's actually rename this one to mesh okay so now on the bullet the goal is to spawn the Bullet From The Soldier's weapon and move it towards the Target and when it gets there it will finally deal damage so let's make a component to handle the data for our bullet let's go into our authoring components and create a new mod Behavior call it the bullet authoring okay so now on this one let's make the usual thing so public struct called bullet it's an i component data for now let's make it empty then a publicly class Baker let's extend Baker on the bullet authoring let's implement this class and as always grab the entity entity get entity make it Dynamic so that the B can move add component entity new bullet like this okay great let's go ahead and save and back in unity let's attach it so here on the bullet object let's attach a bond authoring okay great so now here for what kind of data does our bond need well we're going to need some kind of speed so let's make a float for a speed variable and then we're also going to need to know the Target in order to know how do we reach the target so for that let's store an entity for the Target entity we can do this store the target directly inside there or alternatively we can just reuse our Target component both options work just fine let's reuse the target one in case we need some more custom Target logic then we can add it here but we can also reuse the component so let's do that so we have the speed and let's also Define a pocan for some kind of damage amount that way we can have bullets that deal very little damage and others that deal quite a lot of damage okay so now let's go ahead and pass these in onto the baker so let's go for the bullet set the speed authoring do speed and the Damage amount authoring do damage amount okay great so let's save this and here in the editor let's set it up so for the speed let's put it relatively slow just for testing so let's put two and for damage amount let's say five okay that's great now let's also add the target component and actually for debug purposes we want to be able to drag a Target like again just for debugging just for testing so let's go inside the target here and let's actually pass in the Target entty but again in order to pass it in entty we actually need a reference for a game object over here so make it a public game object for the Target game object again this is just for testing after we have our testing done then we're really only going to set the Target by using the actual Target en but over here Target en let's call get En pass in the authoring component grab the target M object and call it Dynamic okay so you like this let's save and now by default let's give the unit let's give it the zombie unit game object again just for testing just so we preset an object for the Target but of course later on when the units themselves when they spawn a bullet they will give the bullet the actual Target entty but for now like this should be good let's just add one more thing to prevent that visual bug so over here on the bullet let's add the link and group so let's add this one so that when the bullet is destroyed the visual dises with it okay so great so here is our bullet the setup is on correct we have all the data now let's make a system to do some Logic on this data so let's go in our systems right click construct a brand new entities I system call it the bullet mover system and this one let's first keep just our update okay so on update let's do a system api. query now we want to move the bullet so first let's grab the local transform and then we need the data from the bullet so let's grab the ref R we just need to read it for the bullet component okay just these two so let's do for each on the ref RW local transform call it local transform and then ref for the bullet and call it bullet do this in that query let's just format it so put it down there down there break it on the in then on the query break on this one this one close the parenthesis open and close okay great so here's our query now first let's actually move the bullet which means we need to concete to move in Direction which also means we actually need the target so let's also add that one so the ref R for for the Target component so let's grab this one put this one for the Target and then let's calculate a float three for a move Direction and by the way FL three is inside unity. mathematics okay so for the move direction we need to know the target the target position so let's go through the system API call get component let's grab a local transform and it's going to be the local transform of the target let's read the value and grab the target en okay so this returns a local transform for the Target local transform so now we can grab this one position minus the current logal transform of the bullet val. position so with this we get the move Direction and of course this move direction is going to have some magnitude so let's make sure to normalize it so equals math. normalize and let's normalize our Vector okay great so here we have the move Direction now to move the Bullet local transform let's grab the value r w for writing and for the position do a plus equals on this move Direction multiplied by let's go inside the bullet read the value grab the spe multiplied by System api. time. Delta time okay that's really it for the movement we calculate the move Direction based on the target position and the current position and with that move Direction then we just move the unit so that the bullet goes from the start position until the target then let's just use some Logic for testing when do we reach a Target so for that we can access the math library and in there we have the distance we have two functions for this I talked about this a while ago but let me mention it again like name implies one of them gives you the actual distance in actual units whereas the other one gives you distance Square so it's the same thing as the length versus length square that we saw quite a while ago it is really the exact same logic basically when calculating the distance you are actually going to get the square by default and then you need to do a square root of whatever this returns in order to get the final distance but doing a square root that is a little bit costly so technically if you don't need the actual distance number you can just use a square in this case we don't really care about distance we just want to compare it with a number to know if we are close enough so let's use the distance squar and compare the distance between two of them so let's say the local transform. val. position and the target local transform. position so we check distance and basically check if distance is close enough to destroy so let's define a float called destroy distance squared and let's put it point 2f that should be close enough so if the distance is under this then we want to destroy this bullet but before we do let's actually damage the Target now this is actually a bit of a game design question which is do you want to deal damage on the shoot attack system like we were doing or do you want to shoot attack system to just spawn bullets and then the bullets themselves are what deals damage basically both options can work perfectly fine now since we already saw this one about the shoot attack system doing this let's put this on the bullet just to be a little bit different so on the bullet we're really going to do the exact same thing so we can actually just copy this and on bullet mover system okay the bullet is close enough so let's say close enough to damage Target so we get there we grab the target Health yep then for damage amount instead of defining a local one we Define that on the bullet so Arrow damage amount and if that's it this one is going to deal damage to the Target and then all that's left is actually destroying this bullet but again creating our destroying entities is a structural change so let's make sure to use an anti command buffer like we saw previously so up here let's find an entity command buffer and let's go into the system API let's get the single ton and the singl ton of type the N simulation entity command buffer system do Singleton again don't forget the do Singleton so you grab this one call create command buffer this one requires an unmanaged world so that's on state. world unmanaged yep so this one gives us the anti command buffer so then down here after we deal damage let's call destroy entity and we want to destroy the B entity so let's add it up here onto our query so with entity access this means we need to add the entity over here so this going to be the bond entity and Yep this is exactly the one that we want to destroy okay so that should do it our Bol mover system should be nice and workable so we do a query for local transform bullet and Target which y our B has all of these then we grab the target position calculate the move direction towards it move the bullet towards the target then check the distance squared if it is close enough if so deal damage to the Target and then destroy the S so yep like this should be working let's save and over here in the editor just make sure you was sign over here the zombie unit as a Target and now we can test and we should be able to see the bullet move so let's test and if there it is the bullet is moving towards the target let's move these away and as it gets there yep it does indeed hit the target let's just make sure it's actually dealing damage so start playing let's pause let me select the zombie unit just look at it so on the inspector let's look at runtime mode let's look at the health amount okay 100 I just need to move these out of the way so move them out of the way okay and let's see 100 and bullet gets there and yep 95 all right awesome so our logic is indeed working perfectly however we have a bit of a sneaky bug here right now it did work but if we set the bullet speed as super fast so let's go on the bullet on the authoring instead of two let's put at 100 so that it's super fast and and then over here for the destroyed distance instead of this let's use a really tiny number like tons of zeros okay like this so destroy distance is going to be super small and the speed is going to be super fast so let's see exactly what is the problem here let's test and if there it is look at that the bullet goes towards the enemy and look that is constantly jumping back and forth see look at that it is constantly jumping it does not actually destroy it is bouncing back and forth it is not actually hitting the enemy it is not actually dealing damage sometimes might randomly hit but as you can see it bounce around quite a lot now this is a common issue and basically the problem is that it's overshooting the target basically the problem is that the bullet is over here on this side and then on one frame the bullet is going to move a massive amount which means it ends up sort of on this side but this point is not close enough to destroy so the next frame it is going to move another massive amount in this direction and again it is not close enough to destroy so it moves another massive amount massive amount and so on basically the problem is that since the bullet moves so much in a single frame and the target distance is so small it constantly jumps back and forth it never actually gets close enough in order to hit and destroy itself so this is the problem with very fast moving projectiles now the solution to this is basically we need to test to make sure the bullet is not overshooting the Target now there's one very simple way to test for that as the bullet gets closer to the enemy we can just compare the distance towards the target We compare the distance towards the target compare it before moving and after moving and basically if the bullet was closer before than it is after moving if so then we can assume the bullet has overshot the enemy so over here let's do that so we grab the target local transform then let's grab the float call it distance before and let's grab the square distance do a math. distance squared and we're going to do distance just like we saw so the local transform towards the target so let's do exactly this distance okay so we get that then we calculate the move Direction then we move the unit and then we calculate distance again so this is the distance after calculate before move calculate again and then we can just check if the unit if this ballet did overshoot the target so if the the distance after if after is bigger than the distance before if so then we have overshot the Target and if so then we can just place it directly on top of the target position so local transform let's set the value r w let's set the position equal straight on top of the target so Target local transform. position so that one goes straight on top and then even if this distance is super tiny if so it is still going to trigger this and run this logic okay great so yep let's save it and test so let's head on play and see and if there you go even though the unit was moving insanely fast it still managed to hit the target so even if over here we put a giant amount of speed so like 10,000 which guarantees this is definitely going to overshoot the Target even so yep there you go and we can verify we can look on the zombie unit and yep we do see this zombie did take damage all right awesome so that's our logic fully working now let's just put some proper numbers on there so let's go back into the bullet let's put a speed of something like 60 and over here for a destroy distance let's put it Point 2 okay let's save and let's play and see the Bon move and does move Mo does deal damage all right awesome so this working the bullet is working perfectly but naturally we don't want to manually Place some bullets we want our soldiers to be able to spawn them so this means it's actually time for us to learn how to dynamically instantiate objects and dots this is quite simple but does have one interesting Quirk so let's learn how to do that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to learn how to dynamically ineni some entities we're going to have the soldier spawn the bullet which will then move towards the enemy and deal some damage okay so in the last lecture we already created the bullet entity if I head on play the bullet starts moving towards the enemy hits the enemy and Deals some damage so now let's leave that with the exact same behavior but spawn it from the soldiers for then let's go here onto the shoot attack system and here instead of dealing damage instantly instead of that we want to spawn a bullet now spawning an entity is actually quite simple we just need to access the entity manager so here inside the system we can access the state and from the state access the entity manager now from this we can call ineni so just like you essentiate a normal game object you can essentiate an entity but of course the question is how exactly do we get a reference for the bullet object normally when writing normal Mony Behavior code I would just expose some kind of field then the editor I would simply drag the prefab reference but systems in ECS they do not have any game Ming in the world so there's really nothing for us to drag a direct reference then of course there's also the fact that we have to go through the bake process here we are not inating a game object but rather an entity so we need to take the buet prefa bake it into an entity and then we get the entity that we can use over here so one solution is to make a component that takes a game object field and converts it into an entity and we could do exactly that make a specific component just to sort of the bullet prefab but as we're going to be making this entire game eventually we're going to need to reference various object prefabs that we're going to spawn like the soldiers the zombies the bols and so on so instead of just one specific component for each object type we want to spawn instead of that let's create a component to store a bunch of entities references so let's build that in the othering let's right click create a new mon Behavior script let's call it entities references authoring okay let's just clear our error over here let's just comment out this code just to make sure the code compiles okay let it compile so we have our components and now on the entity subscene let's construct an empty game object call it entities references and I like to put it up here so let's just drag it up to the top of the Hier key and now let's attach the entities references authoring okay so now let's open this over here let's write the normal stuff so a struct entity references Implement I component data and then make the baker so class for the baker Baker of entities references authoring then let's implement the abstract class let's get the entity entity get entity get it as Dynamic then add component on this entity new entities references okay great just like this now with this over here on the entities component let's add an entity field so public and Ste let's call it bullet prefab entity yep and now up here on the the authoring component let's set a public of type game object and this going to be our bullet Prefab game object okay and now we do what we've already seen so down here on the entities reference let's set that one equals get entity get the entity of the authoring component dot bullet pref game object with Dynamic okay yep just like this let's save now here in the editor let's just drag our reference so we've got the bullet which actually means we need to make it into a prefab so let's drag it onto the prefabs and on the bullet itself let's get rid of the one over there and on the entities reference let's drag the bullet prefab okay so far so good now back here on the shoot attack system so we've got the code for calling intiate and over here we just need to reference that entity so here's another important question which is how exactly do we get that component now we can't really add it here this is the query that is cycling through the units and the units do not have the entities references component so we can't just add it over here on the query but the goal that we did with this enties references this basically just a single component that exists on single entity that in itself is going to contain all the references that we need so since there's just a single one that means this one is going to be a single them and like we saw previously system API has a really useful function called get Singleton so with this we can very easily get it so let's get the entities references let's get it just like this enties references enties reference equals down okay so with this we can easily get it and then down here on the instantiate let's go inside and grab the bullet prefab en right awesome so this is going to spawn our bullet pre preab let's just Define nty for the bullet entity okay now we need to do is actually initialize it so first let's actually position it on the correct position so let's just do system API call set component and we're going to set the local transform component on this bullet entity and we can actually use one of the helper functions inside local transform it has a bunch of functions like this one from position this one basically takes a position returns a local transform filled in with that position zero rotation and one on the scale so since once again we use our nice trick of having an empty Parent Game object that has a scale of one by default and we only modify the scale on the CH object because that we can use this one so from the position we just need to know the position from where to shoot so let's set it as the position for this unit so let's modify over here the query let's grab a ref R local transform we grab this one and let's put it over here local transform okay we have that and from that one grab the value R and grab the position okay so this is going to initialize the position next let's set up the bullet component so let's go on the system API let's get the component RW of type bullet for this bullet entity so returns a refr w of type bullet so this is the bullet bullet bit of a strange name but it makes sense okay so then on this one let's go inside the value RW and let's set the damage amount so as to where we get this damage amount let's store it in the shoot attack component let's put it over here so that different units with different Sho attack components can deal different amounts of damage so if here just n for the damage amount and then we just pass it through so add it on the authoring component and then over here that one equals authoring do that okay great so now back on this one let's initialize the bullet go inside the shoot attack value r o just for reading and let's read the damage amount okay so that's the B component setup we probably don't need to modify the speed we can probably just leave that one with the speed that the prefab has so final thing is really just a Target so system API let's get the component RW in this case it is going to be the target component and it's going to be that for the bullet entity so this returns a target for the bullet Target and then we go inside this one actually this is a ref RW so then we go inside this one value RW and set the target entity and it will be the same Target entity as the one on this unit so let's go into the target this is the unit's Target value rrow and grab the target entty okay yep just like this this should do it so here we are spawning the bond entity then we are setting it to have on the position from the same as this unit position then we set up the Bullet by setting the damage amount and we set the bullet Target by setting the target empty so y just like this let's test okay here we are let's grab a unit let's get it closing enough and see if it starts shooting and if there you go it does indeed start shooting towards the target all right awesome however I actually forgot to assign the damage so right now the bones are dealing zero damage so let's fix that so on the project let's select the soldier unit and down here for damage let's put it five okay great let's test so here we are let's select one of these move there and start dealing damage and yep and after a while it should kill the zombie so let's see and there you go it did shoot the zombie all right awesome so that did work but now let's actually see one interesting thing so instead of one I'm going to shoot with a ton of them so we have tons of bullets flying around so there you go tons of bullets and as soon as the zombie dies yep there you go we have an error the error is saying the entity does not exist now this is actually basically the exact same issue we already encountered on the shoot attack system here on the B mover system this system assumes that the target always has a valid Target but of course if the target is set as null then this one is going to throw an error so we need to check against null so let's check if the target. value Ro if Target entity equals entity. null if so that means the target is now dead and if the target is gone then over here on the shoot attack system we're just continuing but on the bullet we really don't want it to continue if the target is already dead then this bullet is no longer going to do anything so if the target is dead we want to destroy this bullet so let's use the code that we have down here for destroying an empty let's destroy this bullet right here and then just do continue okay so let's test so here we are let's pick a bunch of these get them all close so they all shoot at pretty much the same time and if there you go it does work so they all shoot a ton of bullets and they all get destroyed if the target is not dead and actually let's just solve one bug that I just noticed right now it has to do with our reset Target system so over here if we play and if we have multiple units all of them shooting bullets all of them firing towards the enemy y there you go we eventually have an error it says the NT does not exist and this error is coming from the bullet mover system so basically the issue is that the bullet mover system this one the bullet still has a Target but the target has since been destroyed so what is happening is actually a very strange thing so basically on frame one the bullet moves the bullet set the target destroy the target okay great then the help that system test that one runs that one eventually cues up the N4 destruction on this one and then on the next frame the NT still as a Target because reset Target system that one does not reset the Target because it is only destroyed afterwards so then next frame the bullet mover system runs and still has Target and that throws the ER except that is not just the ER it is actually a bit more complex than that technically if that were the error we could put the reset Target system put it at the beginning of the frame and that could work so let's try doing that and see so over here on the reset Target system instead of updating on The Late system group trying to update it at the end of frame which again it's only actually going to reset on the command buffer which happens way at the end of frame so even after this one so instead of doing that let's pretty much reset Target on the beginning of the next frame so we can put this on the simulation system group and then we can use order first and set that one into true so like this it should run pretty much at the beginning of the frame okay let's see like this so let's test and pause and yep we can see the reset Target system is running at the beginning of frame okay so let's see if it th still throws that error so they all go they all shoot destroy and nope we still have the error so even though we technically fixed that the a still exists so on frame one the Bon moves it hits the Target it destroys the target then the help that system that one is going to destroy the entity or rather it cues that up and the entity is actually destroyed in this one but for some strange reason on the next frame when we reset and come back over here for some reason the n actually still exists it was queued up for Destruction but it still sort of exists the NT still exists and it's actually only over here on the parent system when the NT is sort of destroyed so by the time we get to this one technically it thinks the N still exists because the target was not reset but the N no longer exists so and we have an issue now this is a very very strange thing I have no idea if this is a bug we can add some logs here just to verify exactly what I'm talking about so let's do un the engine debug do a debug. log let's print out the name of this system and let's also print out the time the unity engine. time and let's print out the frame count the frame number so let's print this one and then over here let's also print if the unit actually exists so Unity engine debug.log and let's print if this unit exists so see this and then also let's go onto the bullet mover system over here let's do the same thing let's also print in order to see in which frame this system is running and then over here let's do the same thing so let's see if the nty still exists Let's test that out on this one okay so let's see like this what exactly does it say okay here we are and let's shoot and kill the enemy and find the error okay the error happened and now let's look at our logs and Y here we do see these strange things so on reset Target system the Target still exists but then on the exact same frame frame 497 on that one the Target no longer exists these false by the way this actually just. null we can verify that let's just print out the entity just make sure we are talking about the same thing so print out the entity like that and same thing on the bond mover system over here print that one let's see everything so let's move the units attack the Target and let's see fire the error there you go there's the error and now we can definitely see okay so on reset Target system so previously it makes sense that the unit does exist unit 196 that's the zombie and that one does exist it does say as true so the entity does exist and now let's see over here so on frame 495 on this one the entity still exists so it still does exist and then on the Bon mover system again on the exact same frame for some reason in between this system and this system all of a sudden the unit stops existing so basically when this runs it does not clear the Target because technically seems like the unit still exists but then down here at the end of the frame on the exact same frame the unit no longer exists I have some testing and seems like the thing that actually destroys the unit is over here the parent system I have no idea why that one is specifically the one that is actually destroying the entity but there's actually one more very strange thing let's add another log here to verify another thing let's call let's call system API that has component of a local transform on the same Target entty so Target value r o Target entty okay let's print this to see if this target entity has a local transform component let's print it out on this one and also over here on the target okay so let's see what both these say let's go ahead and shoot them all okay there's the air now let's look at our logs and okay so frame 493 that's when we have the error and if we look at the frame before on 492 yep The Entity still exists and it does have the local transform component okay makes sense but then on the reset Target system so on this one the entity technically still exists but no longer has that component so this is why I'm saying this is very strange I have no idea if this is a bug or not the entity should really be destroyed on the previous frame but it doesn't but then for some reason gets queued up for Destruction and only the parent system actually destroys it so anyways this is all very strange so the entity that exists that one seems to behave very strangely but we can basically use the has the component of the local transform use that as a sort of proxy so over here for the reset Target system we're going to reset the target if the entity no longer exists or no longer has a local transform component since the targets are always going to have local transforms we can assume that if the local transform is gone that means because the entity is also gone so over here on the reset Target system let's just add that logic so we're going to reset the entity reset the target entity if system API if the entity no longer exists or the entity no longer has a local transform component so that one or that one if it is either of those then the entty will reset to null another thing is here we are running this code all the time even when the target entity is null so that makes no sense that's just wasting a bunch of bunch of performance so up here let's check if Target entity is not entity. null if it isn't then we do this but if it is null then the entity is already not assigned so we don't need to do anything okay so like this finally everything should be working we should not have that error and our reset Target system should now behaving incorrectly it should be 100% resetting the target at the beginning of the frame so over here on the B mover system we can get rid of our logs and yep let's save everything and now let's test so here we are let's move have all the units shoot at the zombie this right zombie and yep there you go no more errors all right awesome so this was very strange but we figured out a solution to our problem we set the reset Target system to run at the beginning the frame and we added some external logic instead of just checking if the entity exists which seems to behave very strangely instead of that we also check for the local transform and that does seem to work so the bullets move the bullets Hit the Target and damage the target with the health below zero then this system runs and cues up the actal en for Destruction next this n command buffer system this one runs and supposedly actually destroys the entity and then on the next frame this one says that the entity technically still exists but does not have a local transform component so you use that to basically invalidate the Target and then when this one runs it no longer has a Target so everything does work so very strange but now all the code is working okay so here's an update that I'm recording later on I believe I have figured out the reason why this is happening thanks to a comment from a student I believe the issue has to do with cleanup components these are special dots components that will basically keep an entity sort of half alive until they are manually removed the transform system use a cleanup component so that's why the entity stays sort of alive until the transform system runs on the very next frame only at that point does that system finally remove the cleanup component for the transform which then finally allows the entity to destroy itself so if I'm correct that this is what is happening then this is not a bug it is working as in tendon it looks a bit strange as to how the N is destroyed in the middle of a frame but it does make sense based on this essentially the nty is only destroyed when all the clean components are manually removed so if while working in your own dots projects you encounter this issue with enties being sort of half dead half alive if so then remember this remember all about cleanup components okay awesome so our bullets are working perfectly fine they spawn they move towards the target deal damage and Destroy themselves however we have a bunch of annoying issues for example one issue is how the bullet is actually spawning from the floor look at that it's spawning from the floor instead of spawning from another the other issue is that the unit is not looking at the Target it is looking away while shooting so let's all a bunch of these issues let's do a bunch of improvements for our shooting logic and let's do that in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to take the bullets that we implemented in the last lecture and fix a bunch of tiny things okay so the bullets that we made they are all working correctly in terms of logic so if I take a unit and I get it close enough to the enemy yep the unit gets close enough and starts shooting so it does work the bullet spawns moves toward the Target deals damage and destroys the target so the logic is working but we have three odd things so the first thing is how the unit isn't really stopping so I move and the unit is shooting and moving at the same time secondly it is not rotating to face the Target and thirdly the bones are spawning right from the character's feet instead of from the weapon so let's solve all those issues first let's s on the stopping so let's go here onto the shoot attack system and on this one we scroll down and right now we are always attacking so if the entity has a Target it always attacks technically we should probably Define an attack distance so that we can have a different find Target distance and attack distance that way our units can find Targets from far away but can only attack when they're a little bit closer so let's go here onto our shoot attack component and let's add an attack distance so public make it float call it attack distance okay like this and let's put it on the authoring component and let's bake it equals authoring do attack distance okay great so then on the shoot attack system on this one let's check if it is close enough to attack for that we need the target position so let's go systemate let's call get component get the local transform component local transform of the target so Target is going to be Target value. Target entity so we get that one so this is going to be the local transform of the target local transform then with this one we can calate distance so math. distance it is math not math F so this one which exists inside the namespace unity. mathematics so this one call distance or actually distance squared since on the fine Target we already have the actual number then over here let's also use the actual number so let's use just the regular distance so there's going to be distance between this local transform do value r o. position and the target local transform. position so distance if distance is close enough to attack let's put this in an if if this distance actually let's test if it is too far so let's test the shoot attack value r o and let's grab the attack distance so if so then that means the target is too far so let's move closer and with that let's tell it to move closer so let's also add another component let's add our unit mover so we add this one for the unit mover and in order to tell it to move closer let's just go into the unit mover set the value RW set the target position to be the target local transform. position okay so y so like this if it is too far it will move closer towards the target so let's just move closer do not shoot and let's continue else so if it is not far enough if so then over here it's close enough so let's stop moving and attack and for stop moving just go into the unit mover and let's write for the Target position and put it the same as this local transform. Target position so yep simple math calculate the distance from this unit towards the target if it is too far let's s the unit mover in order to move closer but if it is close enough then let's stop moving now to go to exactly where it is already stop moving and then shoot okay this should do it so let's save make sure to save both files okay let's test okay so let's just assign the value so let's go in our soldier unit and over here let's see so for the fine Target authoring for this one we set the fine Target let's put it on eight and then for the shoot attack let's put it on seven okay let's see okay let's start let's begin pick up one of these units and if I move close enough yep there you go it does go there and it stops moving and starts shooting target okay so now the unit does stop while shooting and now you might have also noticed something interesting here if I take one of these units and I tell it to go there it gets close enough to shoot now I pretty much can't move away while the unit is still within range I cannot move that's a bit odd basically the unit is getting stuck while shooting and I can't really move it much that's obviously not ideal but so far that is actually correct later on we're going to make a component to override the movement so the player can still manually tell it to move even when there are Targets in range so later on we're going to solve that but for now let's leave the behavior like this so if the unit is within range stops moving and starts shooting okay great and just one more thing like you saw I could actually move a little bit that is because this logic is only running after the timer so if we put this just before that makes a little bit more sense so instead of testing just five times per second if it is close enough instead it's going to test all the time so with that done now let's solve the second problem the rotation so here let's just rotate towards the Target and that is going to be pretty much the same logic that we used on the unit mover system so first let's Cate a FL three for let's say the aim Direction and The a direction will be theer loal transform. position minus this local transform value ro. position that gives us the aim Direction Let's just normalize it so this one equals math. normalize let's normalize our aim Direction and then to rotate this one so local transform let's set the value RW we're going to need that so let's actually modify this one from ref r o to ref RW to modify the local transform okay so then over here let's grab the value RW we're going to want to modify the rotation so for this like I said let's do exactly like we did on the unit mover system so let's def find some kind of Target rotation so Quan Target rotation and we're going to go into Quan and call look rotation take this a direction to Cate that Vector 3 into a quion and use math f. up okay that gives us the target rotation and now for smoothly rotating let's use math. slurp and let's slurp from the current rotation local transform value r. rotation towards this target rotation and by the time we'll be system api. time. on time multiplied by let's go inside the unit mover grab the value r o and grab the rotation speed okay yep so just like this the unit should be rotating to face the target so let's save and let's test okay here we are let's pick one of these units and now if I move a little bit closer and if there you go I can't move away and the unit is indeed facing the target okay great now for the third problem the issue with the shoot position so right now the bullets those are being spawned from the origin of the position and goes towards the origin of the zombie so it spawns from there and hits the floor instead of being spawned on the weapon and hitting around the the center Mass so we want to modify how they are spawned we want to basically have some kind of offset we need an offset for both the shoot point as well as for the Target hit point so first for the shoot position we can go here into our shoot attack authoring and we can add basically that offset so let's make a public FL three for the bullet spawn local position okay we have this and then on the othering component here we actually have an interesting question that relates to dot remember how in the beginning we learn how authoring components do not have to perfectly match dots components so here technically we could Define a flow three that would work we would have to manually write the number in the editor or we can actually do something a bit more user friendly which is let's just use a normal transform field that way we can easily position an object using a transform during edit time but then during runtime everything will be baked into a super fast flow three so let's do exactly that so up here make a public make it of type transform for the bullet spawn position transform and then on the B we just set bullet spawn local position go inside the authoring grab that transform and grab the local position for that transform save that's it perfect now we can easily just position a transform also note very important how we're grabing the local position not the global position this is extremely important we want to sore the offset of the shoot position not the global position whenever the prefab is baked the prefab or the unit itself after being spawned that one is going to move so that is why we do not want to sore the global position instead we want to store the local position okay so now let's set this one up in the editor so let's go inside our soldier unit prefab there it is and now inside let's right click let's construct a brand new empty game object call this the bullet spawn position and now this transform let's just manually position it roughly on the tip of the weapon so something like that just position it put it a bit more to the side make sure it looks good from all angles y pretty much like this maybe lower it a little bit just like that okay perfect and now on the soldier unit let's scroll down find over here the shoot attack authoring and we just drag our normal transform so you can see how it is much easier to be able to manually position a transform in World space that is much easier as opposed to coming here and having to write x y and Zed so this is a great example of how using an empty game object is much much more user friendly than having to write numbers directly it's a great example of how different authoring and runtime data can be quite helpful okay so now let's exit go back save the prefab yep that makes sense and now let's go here on our shoot attack system and let's see to where we are spawning the bullet so right here we are spawning the bullet on this position so now we can go inside the shoot attack we can grab the value Ro to grab the bullet spawn low composition but again this one is a low composition we need to converted into a world position and the way we do that is we access the local transform so that is going to be the transform for this unit for the actual Soldier let's grab the value r o and on there we have a super useful function called transform point and this one is basically going to convert the loc position onto a worm position so we use this we pass in our loc position just like that and that gives us the bullet spawn worm position so a FL three for the bullet spawn World position and then we spawn it directly on this position okay yep just like this let's save Let's test and see if the spawn is spawning on the correct position so here let's just make the bullets a little bit slower just so we can easily see so let's put with a speed of just five and over here on the scene view let's position it some like this so we can easily see if it is spawning okay so let's test okay let's pick up one of these units push it over there get it a little bit closer and see and yep there you go it does work so the bullets are indeed being spawned from there okay great so that's left is the target position we do not want it to shoot at the zombie feet we want to shoot sort of Center Mass and now for this one we don't already have any component that makes sense now technically we could place it for example on the unit component we could add the offset on there but that would be a bit odd because not every unit is necessarily going to be shot so it makes more sense to have a dedicated component one that just stores that position for that purpose so let's go ahead make another authoring component create new mon behavior let's call it shoot victim authoring so this is data for the shoot victim then over here let's do the usual stuff so first let's make the struct call it shoot victim Implement I component data and then over here let's make the baker class Baker of type shoot victim authoring let's do it like this let's implement the baker class let's do entity entity get entity of dynamic entity add the component on this entity and new shoot victim okay great and now let's do literally the same thing we did on the shoot authoring so we have a local position and then a transform so over here for the component let's do a public flow three call it hit local position and then on the authoring component a public transform for the hit position transform okay we have that and then over here on the component set the head log position equals go inside the authoring component grab that one and again important ly grab the local position okay yep just like this so now here in the editor let's go inside the zombie unit and now on this one let's right click construct an empty game object call this the hit position let's move it a little bit up so just like Center Mass and then let's drag the reference we need to attach the shoot victim authoring and drag our head position okay yep let's save let's go back and now let's go here to the bullet mover system and scroll down and we're getting the target local transform and basically using that position as a Target so let's refactor this let's define a flow three for the Target position and let's just refactor all of these instances so find this instead of using that let's use the target position okay they're all sorten so now we just need to assign this so Target position is going to be the same thing that we saw previously so first let's actually grab the shoot victim component so shoot victim of the target shoot victim so target shoot victim then we go inside the target loal transform grab do a transform point a transform point target shoot victim do hit local position this one is actually going to be a float three not a float and yep just like this okay this should do it let's save and let's test okay so here we are let's put them a bit far away let's put it like this so we can see it side by side okay so as I move the unit closer as it gets close enough to shoot and there you go it does work so the bullets Spawn from there and they head on Center Mass then you also made it rotate to face the Target and we also made it stop moving all right awesome so all of this is working now let's just give the bullet some proper settings so over here on the bullet for the speed let's put it back on 160 then on the soldier unit let's make it have a bit more interesting values so for the fine Target let's put it some like 15 then for the attack distance let's put it on like 13 and for the shoot attack timer yep 0 2 makes sense so shooting five times per second and same thing for the fine Target 02 also makes sense okay so yep now our shooting and all the logic all of it is looking really nice so we have a bunch of units they find Targets they move they start shooting and everything does work so that's great but what would be more fun would be to actually have some more enemies to shoot so let's build a super simple zombie spawner in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to build a super simple zombie spawner this is going to be a quick lecture because we have already learned everything we need to do this is going to be an excellent example about how after you learn how dots works it becomes actually relatively simple to build brand new systems okay so far here we have our soldier we have zombies I can approach to the soer and yep there you go starts attacking the zombie and eventually kills the zombie so yep all of it is working perfectly we've got the solders we've got Bonet spawning everything works so now that we have the Bonet spawning working let's also spawn some enemies as well like I said logic is going to be very similar to what we already did so this is going to be an easy lecture first let's begin by making our authoring component to store some data so a new mon Behavior script called the zombie spawner authoring then over here let's write our normal code so we have our our zombie spawner it's going to be I component data and then let's make the standard Baker class so Baker Baker let's bake zombie spawner authoring so not the zombie okay this one and over here same thing as always entity entity get entity let's get a dynamic entity and add component onto this entity a new zombie spawner okay great so now let's think okay what data do we need over here the goal is to spawn a zombie and to spawn a zombie every certain amount of time so let's store a float for a timer and another one for a timer Max and on the Baker on the authoring class over here let's expose a timer Max and when constructing the zombie spawner let's set that one so timer Max authoring timer Max okay just like this let's save and now over here let's make an entty so inside the empty subscene create the new empty game object for the zombie spawner and over here in the whir let's place it over there on that corner okay great then let's attach the components so let's put the inspector back into othering mode add the zombie spawner authoring and let's put the timer at some like 1.5 so we want to spawn one zombie every 1.5 seconds okay that's that now let's make the system to run this so in our systems folder let's go ahead create a new entity I system called the zombie spawner system and now here let's first get rid of these we just need the on update so let's do our on update and now let's do system api. query and for handling this logic first we need to have the local transform so we know where to spawn the zombies let's do ref r local transform okay and then we're going to need our refr W for the zombie spawner okay that should do it so let's put this inside a for each for each our ref local transform call it local transform and then refr W for the zombie spawner call it zombie spawner okay like this let's just format everything ref r o ref RW okay yep here's our query now first let's do the usual thing so count on the timer and reset so let's go inside the zombies spawner grab the value RW and grab the timer counted down by System api. time. Delta time and then let's check the zombie spawner value let's just read the timer and if the timer is above zero if so then the timer is not yet elapsed so let's skip it let's continue but if not then let's run this code go into the Val RW and reset the timer so set the timer back into the zombie spawner let's read the timer Max okay so this handal is the Tim logic and then over here we just want to spawn our zombie so for doing this it's pretty simple we're just going to do the exact same thing we did for the bullet so in order to get the reference let's go up here onto the entities references authoring and let's add another field this is going to be for the zombie prefab entity and then up here for the zombie Prefab game object and then let's paste both them so the zombie pass in this reference as that one okay great so now back in the spawner system over here we can grab that one so the entities references let's grab it system API get the singl ton of type entities references with this we have our component and then from this one inside we can simply grab the zombie prefab entity so now for this we can spawn it so let's go through the state. en manager let's instantiate let's instantiate the zombie prefab enti this will be an enti zombie entity the spawn zombie and let's just position it so system API let's set the component on this zombie entity and the component let's go inside the local transform inside the type itself and let's use from position and pass in this local transform read value for the position okay yep that's really it this should be working as you can see super simple all the exact same logic that we already did so let's save both files and here in the editor let's just make sure to drag the zombie prefab reference so that one and yep let's test okay here we are and yep right away we do see one zombie spawning another one spawning and another one so yep that's it everything is working so our zombies are spawning our soldiers are shooting them and everything is working perfectly so yep this lecture is actually an excellent example about how after learning how dots works you can build new things rather quickly it took a while to learn everything that we just did Here For the First Time learned how to do queries how to set up entities and components how to handle the baking the en intiation the system logic so it took a while to learn all of that for the first time it took a while to change from an objectoriented mindset onto a data oriented mindset but now that we've learned all of that now this becomes pretty straightforward we create components create systems and easily add logic so y with that here we have our zombie spawner fully working now just before we end this lecture let's quickly see the bug that happened a while ago the one where the zombie was destroyed but the visual actually remained like I said we need to add that component so on the base unit we add this one the link en group I said that we need to add this two components that were placed in the scene if we don't add it by default so if I just remove this one from the base unit so remove that one so the zombie unit now no longer has it okay and now if we test let's see what happens to that zombie and that one goes and if there go that zombie was destroyed but it is still moving if we pause on in's hierarchy we can see yep that one has the mesh so the mesh stayed alive but the zombie enti was destroyed however note how that bug is not happening to any of the zombies that has since been spawned so the zombies that are spawned dynamically they do die completely they have no problem but the zombies that were placed during edit mode those destroy the main entity but not the child entity with the visual now this is a really strange issue basically entities that are dynamically spawned they get this component added automatically so here I'm selecting this zombie unit which was just spawn and this one does have this component but if you look over here into one of these Soldier units which again were placed by default in the subscene they were not dynamically spawn these do not have that component by default so that's a very strange thing I don't know if this is an intentional dot thing or if it's an actual bug but thankfully the solution is quite simple we just go into our prefab and manually add that component so the link entity group just like this and that does solve that problem basically for the units over here it is going to actively add this one but then units that are dally spawn it already has this component so it won't add a second one like this if we test so if we have these two so that one will spawn in the scene that one will spawn dynamically and yep they all die exactly as intend finally let's just solve one very strange bug that I just noticed was happening it's actually a similar issue to what we saw on the bullet this time it is happening on the fine Target system it is on this one over here for getting a component so it doesn't overlap sphere and for some reason it is finding an entity that has since been destroyed so since the entity has been destroyed it technically is still alive so it's still shows up in here but then no longer has any components so this one throws an error here are the logs that I had to verify so we can see that on frame 2012 on this Frame the N was killed but then on the next frame that physics query was still finding that en so again it's a very strange thing I have no idea if this is an actual bug for the solution we can just validate this so we can check if system API that exists to check if this en exists so this in set. EN so check if that one does not exist or or does not have that component so if the entity does not exist or does not have that component then let's continue again I have no idea why the overlap sphere is returning with entities that have since been destroyed but still this symbol validation should fix it so let's test and if there you go the entities find the correctly and we have no more errors okay so here we have our object spawning zombies however they are all still going to position 00 so that's a little bit boring it would be nice to give them some random movement so let's create a system to make them walk randomly in the next lecture hello and welcome I'm your kmy in this lecture we're going to learn how to make the enemies walk randomly around their spawn position this is really interesting and requires us to learn something different because the way the mathematics random class works is quite different from the one you might be used to okay so here we have our zombie spawners zombies are being spawned and they constantly go towards position 00 0 now let's create some Logic for the zombies to roam around randomly instead of always going to the same position as usual first let's create a component to store our data let's call it random walking authoring now first let's make our standard logic so a struct for the random walking it's an i component data then we have our Baker Baker of random walking authoring and then we implement this Baker grab the entity and add a component on this entity a new random walking okay good so now let's think what data are you actually going to need the goal is to randomly walk towards a Target position so that means we need to store that Target position so a float three for the Target position that is where this unit is going to right now and then in order to generate positions we want those to be generate around a certain position like a spawn position something like that so let's find a FL three for the origin position then you want to randomize how far from the origin position they should be so let's make a float for the distance Min and another one for the distance Max okay great so now let's pass all of these in to the baker even though for the most part we're actually going to be adding this dynamically so the baker is mostly just going to be used for testing but still in order to test in order to make sure that logic is working let's set it up so Target position go in the authoring and grab the target position and same thing for all the others so the origin position distance Min and distance Max okay let's save and now let's attach this to our zombie here again we want to attach the zombie not to the base unit or the prefab we want just this one just the one that is placed in the scene just this one to have the override so by default zombies should not have this component we're going to Dynam added to some but not all zombies so but on this one selecting the one on the scene let's add the random walking authoring okay great now for the Target position origin let's just choose the exact one that we have so let's say 1102 so 11012 1102 again we're only setting this up manually just for testing distance Min let's say three distance Max let's say 10 okay great so that's a setup and again this one is an override okay so far so good now let's make our system to run this logic so in our systems construct a new entities I system call it the random walking system okay on this one let's keep just our nice update and over here let's do a system api. query and for the query we're going to need the random walking component and we're going to eventually have to update Target position so let's grab it for writing so for the random walking component then in order to tell the unit to move we're going to need the unit mover so unit mover and finally in order to test if we have reached a Target we're going to need the local transfer so ref in this case we probably just need to read for the local transform okay great this is our query now let's do the 4 each and put the ref RW for the random walking call it random walking then refr W for the unit mover call it unit mover and finally the ref for the local transform local transform okay yep now let's see what are we going to do first let's get the distance between the current position and the random Target position so math and let's grab the distance we cannot grab the distance or distance Square although one very important thing here which is we need to make sure that whatever value we use in there it is either the same or smaller than whatever value we're using here otherwise unit mover is going to stop within this distance and then if we test over here for a bigger distance then this one is never going to trigger so if we want we can make this a constant so we don't need to constantly repeat ourselves so up here let's do that public con make it a float reached Target position distance square and we defaulted it to 2f and down here on the system let's use that so the unit mover system and use that and then over here on the random walking system we can go into the unit mover system and from there grab that distance now we just need to make sure that we use the same logic so over here we use less than so let's make sure to use less than not equals well in order to make our code more robust let's also include the equals here just so we don't make any mistakes okay so anyways here let's calculate the distance so distance squared is is going to be between this position so that's the local transform grab the value r o grab the position and then Target position so Random walking value R the target position so if the distance is less than the this one over here the unit mover reach distance if so then we have reached the target distance and if not then too far move closer okay so for the move closer let's just go into the unit mover let's write to it value r w and set the target position equals the random walking grab the value for the Target position okay this is telling it to move closer towards the random position and if we have gotten there if so then this is where we want to change the target position onto a new random position now normally you would go inside Unity engine and use the random class inside of that one you would use that and then call random. range and easily generate a random value this is how I normally do random generation in any of my games however this class this is a class so it cannot be used inside bursted code so let's do it the proper dots way and actually use the random the one that exists inside the mathematics Library this one works quite differently so this one does not have any static functions instead of that it requires an instance to run so let's create a new one so a new random call it random and over here on the Constructor this one takes a scene I will cover what exactly is the seed in a little bit for now let's just use the number one okay so we have this random and from this random then we can now generate all kinds of things we can generate a bll b two 3 4 can generate doubles floats U and so on here we even have a next float 3 Direction however this will generate a random Direction with random values on the X the Y and the Zed however in our game our game has a flat plane area we only want a random Vector That Is Random on the X and the Z the Y should be on zero so instead of using this one let's just use next float and basically construct our own random Direction so a flow three for the random Direction and this one let's do a new flow three and for the X let's do a next float randomize the float between minus one F and plus one F then zero on y we don't want that want to be random and over here on the Zed same thing next float minus one and + one okay this gives us our random Direction let's just make sure that it is normalized so let's go math. normalize to normalize this value okay great so with this we have our random Direction then all we have to do is multiply by the random distance and added onto the origin position and we have our random so let's go inside the random component let's write to it and section the random walking component on this one let's right to it and set the target position for that first let's grab the random walking let's read the origin position and then add the random Direction multiplied by a random. next float next float of the random walking let's read the distance Min and let's read the distance Max okay yep so just like this first we construct a brand new random then we calate a random Direction with random on the X and on Zed we normalize the random Direction and then we assign the new Target position starting from the original position then adding the random Direction plus a random distance so this should be working let's do just a quick log just to see what position this one is returning let's use the debug inside Unity engine debug. log on this random position and actually since I added the unity engine up here now here we have a conflict so if this happens if you want to have both the using Unity engine and using mathematics if so then you can just write the full name here. mathematics and that does work or alternatively let's just not put engine and let's put over here on debug loog Unity engine. debug. Lo okay this should do it so now let's test and let's see exactly what positions we are generating let's save it make sure to save everything Also let's disable the zombie spawner we can literally just disable this game object and it won be disabled in the empty that way only this unit will test so let's see what position this one is going to return okay there's a zombie and it's starting to move and it goes somewhere and now it stops now in reality it is moving meaning that code is running we can see down here messages are constantly being spawned except the issue is that it is generating the exact same position every single time so it's not really random this is one big difference relative to the other random class if you call random. range then it always gives you new values whereas with this random type this one basically requires us to persist with this object we need to create this object then use it to generate a bunch of things and then after generating we basically need to resave this object if we're always constructing the exact same object we're always going to have the exact same generation essenti this random class this one is deterministic meaning if we always create a random always with a seed of one and we always do a next float and another next float and another next float if so then these sequence of supposedly random numbers will always generate the exact same values if we want different values which we do if so then we need this random to persist so instead of constantly creating a new one let's just store it inside our component so over here on the random walking let's create it so a public random against the one inside mathematics call it random like this one side unity. mathematics and over here on the B let's construct random equals new mathematics. random and for the seed again let's use one I'm going to explain that one in a bit okay so we have our random now the random is being saved in the component itself so now over here in our system instead of using a brand new one instead of that let's actually grab the random that is inside the random walking go inside and grab the random but like I said this needs to persist if we do this then we are not actually saving back the data we are taking this random copy and we are updating it by generating all these floats so after we do this we need to make sure to save it back onto the random walking component so for this one let's go into that one random equals random okay yep this should be do okay yep this should be working so let's save everything and test okay so there it is there's a zombie going in that position and then goes up that one and then down and then right and yep it does seem to be working correctly okay great so the unit is going to random positions now let's test with another unit so I'm going to duplicate this one and put it a bit over there okay now let's test with two units and yep look at that how strange both them are going to the exact same position both them are falling basically the exact same order of random positions so it is generating a series of random positions but it is always generating the exact same Series so this is exactly where the seed comes in like I said this random type this one is deterministic meaning that if you use the exact same seed it will always generate the exact same series of values this is how for example games like Minecraft work they don't actually store the entire world the world is generated from a seed so if the seed is the same it will always generate the exact same world so if we want the random position to be different for different units then we just need to use different seeds a seed is really just a number and as long as the number is different then it willon work so on our component over here on the bake instead of hard coding just the number one instead of this we could just generate a random number so for example here we could use the random class do a random. range and generate a random number between 1 and 10,000 something like that so technically we could do this but then we would have a slight problem this is the bake logic which like we already saw the bake logic runs only once it does not run every time a unit is spawn so if we did this even if we randomly generate the random number over here all the units would still end up with the exact same seed so we need different method in this one and now for units place in the scene we can basically just Define here on the authoring component a random seed so a public in random seed actually this is meant to be a uint okay a random seed then over here let's pass it in authoring the random seed and then for units that respond dynamically basically we're going to use a different method in order to generate a new random component whenever the unit is spawned let's first make sure that it works on the ones on the scene so let's save and now here on our Bakers for this zombie let's set this one with a random seed of some random number let's say 56 and for this one let's say 32 so as long as they are different it won't work typ with this let's play and test and if there it is right away they are moving to different positions and they are randomizing different locations on all the time all right awesome so yep everything is working correctly now all we need to do is just add the same logic onto the zombie spawner so over here on the zombie spawner system we count on the timer and then we spawn the zombie entity okay so far so good then afterwards let's add that random component however adding a component will be a structal change so if here we do state.ent manager add component data if we do this this actually going to throw an error now I'm actually not entirely sure why this one throws an error but inen it doesn't but either way Yep this one will throw an error so instead let's not immediately add a component instead let's use the normal en command buffer so up here let's just grab it so the entity command buffer and let's simply go into the same one so system API let's get the single ton for the end simulation command buffer system let's go inside grab the Singleton for this one and let's call create command buffer passing the state. world unmanaged okay so we have the ant command buffer and then down here now we can do that one so we can call add component and let's add onto this zombie and add a new random walking component and now here we just need to initialize all the parameters so first for the origin position the origin is going to be wherever this unit is being spawned so let's use exactly this one and for the first Target position which is supposed to be a random position but we can set it to exactly this one which means it will generate a random position on the next frame okay and then for the distance distance Min distance Max let's actually expose these values on the over here the zombie spawner component so let's go to this one and do exactly that so a public float random walking distance Min and then we have the distance Max let's expose these in the authoring component and pass it in in that one so both the Min and the maximum okay and now back here on the zombie soner system over here we can go inside the zombie spawner let's read it in this case the distance Min and then the distance Max okay so the final component is just the random one let's construct a brand new random and for the seed let's start with just one just for testing again this will not exactly work but let's test we just need to make sure to assign these values so back in the editor here let's go on the zombie spawner and first of all let's enable this game object okay and let's set up these let's say three and 10 okay that should do it let's disable the other two zombies and let's test and see where exactly these spawn zombies will go okay that one spawn is going down there that one spawn going down there spawn going down there so yep we have the exact same thing since all of them are being spawned with the exact same seed all of them are following the exact same random positions now to solve it like I said you could randomize the number or for example use the clock time that could work but with those technically we could still end up with multiple units using the exact same scene so something that is both simpler and actually guaranteed to be unique is to really just use the zombie entity use the index so we go inside the entity and we grab the index and Y this basically an in value that defines the index for this entity this one is guaranteed to be unique for all of the alive entities so this way basically it guarantees that every single zombie entity is going to have a different random see it we just need to convert this into a uint because that's what that one takes okay so that's it let's test and see if all of them are going to random positions and by the way here on the random walking system we can now get rid of our log just like this okay so there's zombie first one going up second one going a bit more to the side that one going over there that one going down and that one going down so yep they are indeed going to random positions each zombie that spawns is getting a different seed and because that they are generating different random positions all right awesome so here we implemented a really nice random walking logic as units spawn they randomly walk around their spawn area in doing so we also learn how to work with the random type inside the mathematics library and how that type is different from the default Unity random class by using this type instead of a random class we can now use burst to make this code super fast so with this our zombies are looking quite nice they spawn they move around I can use my units I can approach and I can shoot them however one thing we don't have is some kind of visual for the health right now the enemies they just take some bullets and eventually they die would be nice to have some kind of health bar to be able to see what health they have so let's add that in the next lecture hello and welcome I'm your codm in this lecture we're going to learn how to create a nice health bar now this is a very important lecture because it requires us to learn some tricks for how to scale transforms and also make them face the camera we need to do that and we're also going to make sure that our health bar is as the couple Des can be from the rest of our code which requires some interesting logic okay so here we have a bunch of stuff working we've got our units we've got some enemies being spawned and they're randomly walking around then I can move with my units around and when they get close they shoot the enemies but there's no feedback there's no way to tell which of these enemies has been damaged or not they have a health but there's no way to see it so let's build a nice health bar now first let's set up the structure for the Heth bar and in terms of building that you might first think to make it just in UI now that's a good option if you're making a game kind of like an FPS where you just have your own health but in an RTS with tons of units in the world you really want a health bar to also exist in the world you want a health bar per object on top of each object and in terms of making a world health bar let's just go inside the Bas unit yep inside this prefab now one thing I normally do when I want to make health bars for units is just create a world space canvas so go into UI create a canvas and build this then over here on the render mode set it to World space and then inside this canvas create images for displaying the health bar that's what I normally do however like this we are not using dots specifically not using dots rendering so if we use this approach our game will end up being very slow since we're going to end up having hundreds or even thousands of canvases being rendered so let us not use this approach let's do something else we want to render it just like our normal units using the same rendering system so let's use a normal mesh Filer and mesh render now for the setup first let's construct just an empty game object name this the health bar let's put it first of all in 0 and then just lift it up on the I something like this okay now inside it let's make Another Empty game object call this the background and for this one let's add both a mesh filter and a mesh render for the mesh filter let's go with a quad and for the mesh render let's choose go over here on the materials General and choose the gray material and if there it is it's on the other side but don't worry about that like I said we're eventually going to make this face the camera so it doesn't matter that it's only rendered on one side so on this let's scale it so on while let's put it something like3 okay we have a nice rectangle this is going to be our background now let's duplicate this so duplicate the background name this one the bar let's move it on the Z just by a tiny bit so literally over there on the Z by 0.01 that's just so we don't have issues with Z fighting if both of them are on the exact same position then we're going to see some flickering but if they are slightly off like by that amount that is more than enough that will make sure this one renders on top of the other one okay so for this one we want it in Red so let's choose over here the health bar material yep just like that then for scaling the health bar as unit takes damage for doing that we're going to want to modify over here the scale modify the X just like this except not really like this this is scaling from the center this is not what we want usually health bar scale from the sides now doing that is actually quite simple we just need to change the pivot for this object and the way we do that is with another game object so inside the health bar let's construct a new empty game object call this one the bar and this one let's offset it to the left side in this case since the background bar has a size of one let's put it literally on minus5 and that makes it perfectly on that side and now we can make the one the visual a child of this one and just like this now if we scale this one on the X yep now it does scale correctly okay so far so good so this going to be the structure for our health bar now let's apply some logic to it so first let's make the component to store some data so on the authoring let's create a new mon Behavior script for the health bar authoring on this one let's make the same stuff as usual so public struct health bar I component data and that appear make a class for the baker Baker health bar authoring and let's implement this get the entity and add a component on this entity a new help bar okay just like this so now over here for the data we're going to essentially need references to two things first we're going to need references to the visual health bar so let's make a public of type entity for the bar visual entity and secondly we're going to need a reference to the parent entity that has the health component so let's put public entity for the health entity yep just like this and like we saw previously on the baker let's add them as game objects so the this one is going to be a game object for the bar visual game object and another public game object for the health game object then over here we need construct for the bar visual entity let's call get entity on the authoring dot this Cas the bar visual game object with Dynamic okay and same thing for the other one for the health entity go inside the health game object okay yep like this let's save then here in the editor let's choose the health bar so this one the parent game object and let's add the health bar authoring and drag the references so for the bar visual object that is this one again it is this one not the child one that actually has the visual we want the one where we made the special pivot so let's drag this one and for the health the health is going to be on the base unit so yep just like this by the way here you might be thinking wouldn't it be better to place this component either directly on the bar visual or perhaps on the unit that actually has the health component that way technically we would avoid one of these references and the answer is yep you could do that and it would likely be a tiny bit faster since we would only need one reference but the performance difference is so tiny and in doing either of those methods we are really complicating the structure of our object either we would have this health bar component inside a CH object that would make it look very messy with the health bar the main health bar that one having no component or if we place that one on the unit object if so then we are kind of tightly coupling this unit to the health bar we want it to be as separate as possible so that is why I prefer keeping things like this keeping the help bar over here with references to everything that it needs that way this health bar over here is as self-contained as possible which is important because later on in the future we are going to have things other than units that also have health like for example the buildings and by keeping this structure by keeping this one as self-contained as possible we are going to be able to reuse this health bar on other systems other buildings and so on but again let me also point out that refactoring is always a possibility so if later on you find out that for some reason your health bar is your main performance bottleneck if so you can always come back here and refactor so always remember refactoring is always an option okay so here we have our health bar we have the component with all our data so now let's make the system to run it so in our systems let's create a new entities I system for the health bar system and now here let's do our update and on update let's do system api. querying let's query for the health bar and for this one we're really just going to read the references so let's make it ref R for our health bar and this is the Min one that we need so let's just do this so for each doing a ref rro on our health bar like this like this okay so then from inside this health bar inside we have references to the bar Visual and the health entity so let's go on the health entity and let's grab the health component so system API let's get the component component of type Health inside of this entity so this returns a health component okay and now for calculating the size for our health bar we're going to need to normalize our health so let's define a float for the health normalized and normalizing the value is actually quite simple we just take the health amount and divid by the maximum so that means we also need to sore the maximum so we're here on the health components sort the health amount and the health amount Max and let's make sure to pass this in over here on the baker so the health amount Max authoring that Health amount Max okay so now over here the health amount divide by health. Health amount Max and let's just make sure to convert one of these into a float so we get a nice normalized value now with this value we can really just apply it to the bar visual so let's go system API get the component of local transform to modify the scale and we want the one that is inside the health bar let's read the bar visual entity so this Returns the local transform for the bar visual local transform and actually we want to modify it so instead of get component let's use get component RW which returns a ref RW this makes it super easy to modify this one so then let's go into the Val RW and set the scale set the scale to the health normalized okay yep just like this now you might be guessing this won't exactly work but still let's say like this let's save everything and then here in the editor let's just make sure to assign the health amount Max over here on the base unit let's go on to the health authoring and set the health am Max also to 100 okay that's it let's exit and make sure to save the base prefab and now let's test okay so here we are and right away our units do have their health bar now they are sometimes visible sometimes invisible that has to do with the rotation because again it's only visible in one way but that's not a problem we're going to solve that in a little bit when we make sure that the health bar always looks at the screen and now if we try attacking in unit to make it easier to see and let's actually stop playing and over here let's disable the zombie spawner and just enable this one just so we have just one to test okay let's see so we have that one and now let's move closer with one of these units and see if that one starts taking damage and there you go it does start taking damage there's our zombie with a health bar and the health bar is indeed shrinking however it's shrinking in a strange way it is not going right to left instead it's actually scaling across all the axes at the same time whereas the goal is to only scale the visual bar just on the X so this means that it's time for us to look at the baking logic so over here on the health bar authoring so far we've pretty much always been using the transform usage flags and putting them as Dynamic now this great this means that the transform can change but making it like this also makes it so that the scale can only be uniform meaning it has to have the exact same scale on the X Y and Zed it cannot have a different thing on the X different on the Y and Z now this is a performance thing it is much faster if the scale is uniform but in our case we do do not want it to be uniform we want the X to be something we change and we want the Y and Z to remain at one so here for the usage Flags instead of dynamic let's go with this one non-uniform scale and if just like this let's save and now if we inspect one of these entities over here on the zombie unit let's go select the health bar and select the bar so this is the one that has a reference and the inspector if we go into runtime mode and up here we do see now it has this component a post transform Matrix this component basally applies a second transformation on top of the regular transform which in this case will allow us to scale the visual just on the a you can note how for example on the main zombie unit which set as just Dynamic Yep this one does not have that component and also by the way even without explicitly baking something as non-uniform if the game object has a non-uniform scale like for example the background where we set yep we set a non-uniform scale with a yf3 just by doing that it does automatically add the post transform Matrix so if in the authoring game object you already modified scale to nonuniform then when the entity gets baked it already has this component or of course if we are explicitly over here saying non-uniform then it does also add that component okay so here on our health bar system instead of working with this local transform instead let's go system API let's get the component r w in this case let's grab that one so that's the post transform Matrix and it's from the health bar value r o and let's grab the bar visual entity so this will return a ref RW of post transform Matrix let's call it the bar visual post transform Matrix okay yep we have this one and then from that one we can go inside the value r w and for the value this one takes in a value of type float 4x4 so let's put that float 4x4 this one over here basically it's same Matrix 4x4 and this one thankfully this one has a helper function over here for the scale and we can set the scale and there's a version that takes x y and Zen so that's exactly what we want let's put on the X the health normalized then on the Y one and Zed also one and Y just like this let's test okay here we are and let's approach just with one of these soldiers and start shooting and seeing and Y there you go it is indeed working look at that the scale is indeed modifying perfectly exactly right to left exactly as we want it all right awesome so it's working now let's add three more features to our health bar first one is let's make it look towards the camera so basically we just need to grab this local transform for the health bar and make it face the camera so the way we can make it face the camera is essentially by grabbing the camera's forward vector we apply that same forward Vector to the bar and it will be looking towards the camera so first let's grab the vector so Vector three for camera forward and we can grab camera. Main and grab the transform. forward and here the sectionally added system. numerics that is not the one we want we want the vector 3 that exists inside Unity engine so y like this one camera. main and yep like this except this might actually throw an error it has to do with the difference between the lifespan of dot systems and the lifespan of just game objects on the scene that has to do with how the dots bootstrapper Works how it automatically creates the systems and starts them running so on the first update the camera might not exactly exist it might only exist on like update 2 or three so let's add some safety code here so by default let's default it to Vector 3.0 and then check if camera. main is not NN so if the camera has been initialized if so then we can DET set it so camera forward equals this like this okay so we have our camera forward Vector now the goal is for the health bar to beot rated towards this exact same forward Vector however this is actually a tricky thing that took me a while to figure out while researching for this course if we just take this and we apply it to the bar rotation which by the way let's actually include over here in the query let's include a refr W Local transform and over here we need to include that one so let's put the ref RW local transform okay we have this now if we go local transform and write towards the rotation if we do this and use Quan do Lo rotation to convert this one the camera forward convert this one into a quitan let's use math. up okay if we do this let's see what does this do and nope it doesn't actually work doesn't actually seem to do anything look at that as the units rotate it is still clearly not looking towards the camera basically this is actually the exact same issue that we had on the bullet spawn and how we need to have a local position and converted into a global position over here it's the exact same thing the health bar that one is a child of another transform so we need to convert the camera forward from a GL Global Vector into a local Vector now thankfully that's actually quite easy we just need a reference to the parent local transform and the parent is going to be the same one that has the health component so let's go system API let's get the component and it's going to be the local transform of the health bar let's grab the value R and the health entity so this one is going to be a local transform for the parent local transform and now we can rotate this health bar and for the rotation for that we use the parent local transform and we use inverse transform rotation so this will convert a global rotation onto a local rotation exactly what we want so let's do it just like this and yep with this let's save and test and yep right away it does work so our units can move around and you can see yep like that it does work all right awesome okay so now for the second thing let's make the bar only show up if the bar is not full now this is really a personal preference kind of thing but since our game is going to have tons of units I think it looks better if the bars aren't always visible by default for doing this we can use some super simple logic so over here we have the health bar normalized and when the bar is full we can just hide it so if this one if it is 1f if so the health bar is full so we can hide this so local transform we can go into the value RW and set the scale in order to hide it let's set it to zero and if not then let's set it into one and if that's it super simple let's test and if right away the bars are not visible so the zombie over there has no health bar but as we approach and starts getting shot once get shots once yes there you go it does show up the health bar and it does go down okay great and now for adding a really nice bonus in order to make this code slightly more performant let's make it only update when something actually changes as opposed to what it is right now where even these units who have the health bar invisible even these are still constantly updating their health bar on every single update so that's really quite tful for this we can once again use the exact same event logic we've already used for the unit selection logic let's use an event to the f when the health changes so let's go over here onto our health component and let's set an event so public bow on health changed I'm using change just in case it supports both Health going down taking damage and health going up healing okay so we have this and then let's go into our reset event system and on this one let's do the same thing let's reset our event so in this case that's the health so we go into the health for the component query for health and we don't need the WID present okay cyle through the health then health. Val RW and on health change reset into false also by the way one thing that I forgot a while over here for the update and group right now we are already making it updating the simulation system group that's great but this is not necessarily guaranteed to end up at the end looking at our systems window we can see yep there's the reset event system and just by chance it did end up at the end but like I said this is somewhat random between Unity builds so on your PC it might not end up at the end let's make it explicitly update only at the very end so for that over here on the attribute we can use the option or the last and set this one equals true okay now this one will guarantee it runs at the very end of theate simulation system group okay so that's the reset that sounds good and then on the health bar system on this one first of all let's make it run before the events are reset so we can just put update and group on the type of on The Late simulation system group okay then down here for running our logic now one thing is the rotation here this one we need to run all the time not just on the event update however we only need to run it all the time if the bar is actually visible so we can check if the local transform the value r o do scale if the scale does have one F then the health bar is visible yep if so the health bar is visible great now let's check if the health has been changed or not so here if health and let's check on health changed so if that one is false meaning the health did not change if so then let's just skip let's just continue and if it did change then let's continue running this logic by the way let's get rid of these comments just like this okay this should do it and to validate let's just do over here debug.log and say health visual update okay let's see how often this one runs it should not run on every single update over here the logic should be set up correctly all that's left is to fire off this event so let's go here onto the bond mover system this is where we are actually dealing damage to the units over here we are counting down the health so really all we need is just over here on health changed and set it to true and yeah that's it so this one all set it to true then the health bar system will update it and then reset events we'll reset it back into false now just one more thing over here on the health authoring let's defa it true just to force the health bar to actually update so this one equals true okay just like this let's save everything and let's test looking out down at the log we can see we have a bunch of updates so all of them updated just once as soon as they starting which makes sense but they are not updating right now now if I take one of these units and I move it should only update once every time that unit is shot and there you go only when the unit is shot does it update and now when STS moving yep there you go it stops updating all right awesome this is working perfectly so let's remove the log now let's just solve one issue it's this bur eror over here it is on the health bar system and selling us the manage function Unity engine camera get main is not supported so this is the usual burst limitation of not being able to access managed objects and the camera itself that is a managed object so we cannot access camera. main inside bursted code now even though this is an error it does not stop us from playing the game so we can head on play and everything does work so it's technically not a problem however this error existing that does mean that we cannot make a build if we try we get an error and the build fails and thankfully in order to solve this actually quite simple here on the alar system the issue is we cannot have both burst compile and grab the camera. main so to fix this let's really just disable burst compile on this function so like this this will not be using burst which means it will be a little bit slow but will not throw this error and also by the way don't worry too much about the speed of this system we're going to refactor all of this use the job system in a future lecture okay so that's really it let's save and I'll wait for it to to compound and Y we have no more errors okay so here everything is working perfectly the units have a health bar and that health bar only shows up when actually takes damage so if I move now it does show up the health bar updates to show the health of the unit it correctly scales it shows and hides depending on if the unit is fully alive or not and it only updates when something changes so that's perfect here we built a really nice salar but our units are also still looking quite a bit too basic just shooting the bullets it doesn't have much impact so let's add a nice visual light and learn about companion components in the next lecture hello and welcome I'm your Cod monkey in this lecture we're going to add some nice lights to our shooting visual this will also help us learn more about what are companion game objects and how they work alongside dots entities okay so here's our game so far we have our units we can control them there are some zombies and our units can approach and they can shoot so yep that works but the shooting looks a bit too basic just like this the bullet simply spawns let's head some nice lights when we shoot so first things first let's just build our light so inside the NTI subscene let's construct and let's actually build the light directly we could make it a child of a game object this one is going to be super simple so let's just create a straight Point light let's name this the shoot light then over here for the settings for the color let's make it a slight orange okay like this and for the intensity let's make it really intense like 20f and over here on the scene let's just lift it up a bit so we can see the intensity yep that's good and for the range let's put a bit lower just five that's good enough and down here for the Shadows let's maybe go with hard Shadows but with low resolution okay that's it pretty simple and also by the way here we do see a message that has to do with Shadow Atlas technically we could disable Shadows here but I think with hard Shadows looks a little bit nicer so what we can do is just go into our settings go into our render pipeline asset and over here on the lighting tab we see additional lights and over here we see the shadow Atlas resolution so if you want you can play around these values or disable Shadows like I said both Works my case I'm going to move this up to 4K just because I really like having some lights okay so yep that's good here we have our shoot light set up and again if we look down here onto the empty baking preview we can see there are a bunch of companion game object components so this is just like we saw in the beginning of the course for the Sprite render basically Unity dots does not currently support lights natively so what it does is basically creates an entity that will match exactly this game object so both the entity and the game object are linked if I move the game object around the entity moves with it but importantly the game object still exists as opposed to the normal baking process where the game object is gone and all the N exists meaning this is not going to be as performant as using native dots entities but it's still going to be fast enough and it also means it is possible to use lights in our scene basically the fact that it's compan game object doesn't actually mean you can't use it it just means it won't be as performant in this case doesn't really matter too much because our light isn't going to live for too long but do be aware of compan game objects and how they are special okay so what exactly do we want to do with this light basically we we want to spawn it when unit shoots and then destroy itself after a short amount of time so let's handle the spawning logic which for spawning first of all we actually need to make this into a prefab so on our prefabs folder let's just drag it over there okay great then for dynamically Spa in the prefab we need to add the reference over here on our entity references so over here let's add the same thing so another field for the shoot light prefab entity and up here for the shoot light Prefab game object and then over here same thing shoot light game object okay okay like this then for spawning it's on the shoot logic so let's go into our shoot attack system yep over here let's scroll down to where we are spawning our bullet here it is so we spawn the bullet and afterwards let's spawn the light so let's use state. entity manager to instantiate let's grab the enties references and we can grab the shoot light prefab so this will be an entity for our shoot light entity okay great and then all we need to do is just position it and it's going to have the exact same position as the bullet so we can actually just copy that one in order to end up on the exact same position so it should light empty spawn on the exact same position okay that's really it just like this we should already be spawning the lights so let's test over here let's just delete the prefab from the scene and let's go over here on the enties references and let's drag the shoot light prefab okay let's test okay here we are let's select just one soldier move closer and let's see and there you go it does work it does spawn the light okay great now obviously we need the light to eventually vanish so let's do that let's make a component to store a timer so on the authoring construct a mon Behavior script shoot light authoring then over here the usual standard stuff struct for the shoot light I component data and up here our Baker shoot light authoring grab the entity and add a component on this entity a new shoot light okay so now what that do you need is really just a timer so up here a public flow timer and let's also Define it up here on the authoring component and then just pass through so so super simple and stuff okay let's save this in the editor let's select the prefab so the shoot light and let's add the shoot light authoring component and then for Tim let's put it 0.05 so this is pretty much just going to spawn for about one or two frames okay so that's good that's data now let's make a system to actually destroy it so on our systems let's construct a new entities I system for the shoot light destroy system and over here let's keep our update just like this let's do a query so system API let's do a query query for our shoot light component and we're going to want to write to it so ref RW and this really the only one we need so let's do a for each ref RW for the shoot light okay we have this and over here let's count on the timer so shoot light let's go into value RW for the timer minus equals and it's on system api. time. Delta time and then if this one is low enough so the shoot light value r o grab the timer if it is under zerof if so then we want to destroy it and for destroying as usual let's use an N command buffer so ENT command buffer and let's grab it so system API get the singl ton of the N simulation in command buffer system grab the singl ton and from the singl ton create the command buffer and just pass in state. world and manage okay so then over here we can just go en command buffer and call destroy entity and now here we need a reference to our entity so let's modify our query here and add withd nty access which means we need to add our entity over here so entity entity let's just format this tip like this pass in and Destroy This entity okay like this so let's test so here we are let's move with one see if it spawns and destroys itself and it there you go it does spawn and does destroy itself all right awesome so this working perfectly fine however here in our shoot attack system on this one I don't think it makes sense for this system to be responsible for both spawning the bullets and spawning just a normal visual effect this system should really only handle logic so let's separate the visuals from the logic like I normally do let's use events except of course we have to use the special dos events so let's go here on the shoot attack component and on this one let's make an event so public ball on shoot okay great so now let's go on the shoot attack system and on this one instead of doing all this let's just go into our shoot attack value r w and set on shoot equals true then on the reset event system on this one let's reset it so let's make another query this time listen to the shoot attack and let's go on that one and set the on shoot back into false okay so like this all of it is working so let's save all of it all we need is now an event to actually spawn the light so let's make a new system so new entities eye system called the shoot light spawner system and over here first let's make it run before the reset events so as always update and group on the type of for theate simulation system group and let's get rid of this one and this one okay so now here let's do a query system API without query let's cycle through all the shoot attack and we just need to read it so ref on the shoot attack let's do for each ref r on the shoot attack shoot attack in this okay so now let's test if shoot attack let's read the value if the on shoot has been triggered if so then here we want to spawn the light so let's go on the shoot attack system over here let's just copy this logic so let's go over here paste this logic which means we need the entities references so let's also copy that one go up here just like this okay so we have that one we can spawn the shoot light except for setting it up for setting up the position this is a bit a tricky question here we don't know exactly where we should spawn the light all we know is that an event just happened now technically we can go inside the shoot attack and grab the bullet spawn local position we can grab that and do the same cations so that would work but this is also the perfect time to see how we can add extra data with our events now instead of storing just a bullion which really doesn't store any data really just stores true or false so instead of that let's create a new struct to store all our data so inside here let's make a public struct call it Ono shoot event then inside let's have a bullion call it is triggered this will be true when the event is triggered and then reset and then let's add any extra that we want like in this case we want a flow three for the shoot from position okay yep like this and I on the UN shoot event instead of being of type ball it's of type on shoot event and over here on the shoot attack system instead of just setting that one to True let's go into the on shoot and let's set the is trigger into true let's actually rename this instead of is trigger is triggered okay the event is has been triggered and then for the shoot attack for the other one for the shoot from position let's pass in the B spawn wor position okay yep that one does and over here let's not spawn that one great now let's go onto the reset events and over here let's modify that one so we just need to reset the is trigger great and finally over here on the shoot light spawner on shoot dot is triggered if the event is triggered let's go inside again the shoot attack let's read the value the on shoot and here we have the shoot from position and now we can convert okay this should do it so now let's test and let's also enable all our zombie units okay let's test so here we are and if I move a little bit closer and there you go it is indeed spawning the lights on all of them all the units they do see they do fire and they do spawn some lights all right awesome so here we have added a really nice light to our shooting everything looks quite a bit more Polished in doing so we'll learn more about companion components and very importantly we'll learn how to separate our logic from visuals using events and we learn how to handle events and dots with extra data okay great so with this our units can now shoot it would be nice for the enemies to also have some kind of attack so let's Implement a nice melee attack for the zombies in the next lecture hello and welcome I'm your codm in this lecture we're going to learn how to handle melee attacks so our zombies will find Targets move closer and attack okay so we already have quite a lot of things our units can move around they can find Targets and they can shoot but the zombies are still not doing anything so let's add a nice meley attack onto our zombies and this task is actually a great example of one of the powerful features of dots or rather a data oriented design it's the fact that systems and components really only care about themselves we already made our fine Target component in system that logic only cares about finding targets it does not care if the target is going to be attacked with a bullet or with a fist it does not matter it just finds targets that's it so for our melee action we can reuse the exact same fine Target system all we need to do is make sure that zombie already has the fine Target system which it does so if we inspect the zombie unit and we scroll down yep it already has the fine Target authoring and already has the target authoring so the zombies are already good enough for finding targets let's just increase the number over here just for testing let's put it 15 okay great so just like this already working let's just quickly validate it so over here let's get one of these units close to a zombie and now if you pause and let's select one of these zombie units and let's go put our inspector into runtime mode and find the target component and if there ises any yep it did find a soldier unit so yep just like this our zombies are already finding targets like I said this is a very real use case of the benefit of reusing systems and dots as long as we are clever with the components they use and how we make our systems as long as we make them as self-contained as possible then we can reuse them in many use cases so since finding Target is already working let's just handle the Melech Logic on top of that so first let's make a component to handle our data so in our authoring let's go create a new mon Behavior script for the melee attack authoring and on this one let's first make the whole thing so struct for melee attack it's an i component data and on this one let's make the baker class as always Baker on melee attack authoring let's Implement that one get the entity and add a component on the entty a new melee attack okay so now what that do we need just like in our shoot attack we're going to need to have some kind of timer we don't want to attack on every single update so up here the usual float for a timer and another one for a timer Max and let's expose just the timer Max on our authoring component and pass it in over here so timer Max equals authoring timer Max okay yep just like this let's attach this component to our zombie so here let's select our zombie prefab yep and let's attach the melee attack authoring then for the Tim let's put it some like 0.5 okay so far so good now let's make the system to run this so in our systems folder let's construct a new entities eye system for the melee attack system on this one let's keep just the update just like this let us cycle through everything so SYM API doing a query and first we're going to need the local transform we're eventually going to need to know if this unit is close enough to attack we're just going to read it so ref R of the local transform then we also need the melee attack that one has a timer so we're going to write to it so our melee attack and we're also going to need to know what Target we're attacking so ref R for our Target okay let's do the four each for this ref and the local transform local transform then a ref RW for the Mele attack and finally ref for our Target okay y That's our query so now first let's check if the target is null so up here let's check Target value R and if the target entity is entity. null if so that means we have no targets so let's just skip let's just continue Okay then if we do have a Target here let's see if the target is close enough to attack so for that let's grab the target position so grab the local transform for the Target local transform we go inside the system API get the component of type local transform of the target. value Arrow Target ENT okay with this we have the teral transform so now for finding the distance let's you mat that distance and again we don't really care about the actual value so let's use distance Square the distance between the local transform. value. position so this position distance between that and the target local transform. position let's check if this distance is close enough to attack so the fin a float for the melee attack distance squared and let's put it at some like 2f and we check if the distance if it is bigger than this then that means the target is too far and if not then Target is close enough to attack now over here on doing just a distance check this actually going to have an interesting error an interesting problem but we're going to see that in a little bit for now this is great so we test distance between this unit and Target and if it is too far then really over here all we want want to do is move closer so let's actually also add a ref RW for our unit mover component and let's define it up here as well the unit mover so if the target is too far let's move closer so let's value our W set the target position to the Target local transform. position okay and if the target is close enough to attack then first let's stop moving so let's stay moving exactly where we are so set down to that position okay we stop moving then let's count down the attack timer so let's go inside the m attack the value r w and for the timer let's count down by System api. time. Delta time count down the timer then just check if value for the melee attack let's read the value of the timer and if it is still above zero then it's not yet time to attack if so let's continue but if not then let's reset the timer so go in the value RW for the timer and set it to Mele attack let's read the timer Max okay so then down here let's just attack our enemy in this case let's deal damage to the Target Health instantly ly so let's do it just like we did on the bullet so let's actually go onto the bullet mover system and over here let's see how we are dealing damage and yep that's it very simple we get the target deal damage and fire the event so up here same thing let's grab the Target and then just deal the damage amount so that kind of means we also need to store the damage amount so over here on the mill attack let's store that public H for the damage amount and we also need it on the authoring component and then down here so Dage amount authoring Dage amount so then over here we can just just go into the melee attack and read damage amount apply that damage to the health fire the event and yep that's it so just like this it should first test if it has a Target if so then check distance if too far move closer towards the target if close enough to the attack then stop moving and actually attack okay so let's save everything and let's test here in the editor let's just make sure that the zombie actually has quite a bit of health so let's keep just one zombie let's get rid of the other ones just temporarily let's put that one on authoring and let's see for our health component let's put it with 10,000 instead of 100 and on the melee attack authoring let's also make it give some damage but let's apply it on the prefab itself let's give 10 damage okay with this let's test so here we are let's take one of these soldiers get close enough for the zombie to start chasing me and there you go the zombie is chasing me the unit is attacking and now as zombie gets close and yep there you go as soon as he gets within range it does indeed deal damage all right awesome so yeah part logic as you can see it is already working thanks to reusing our fine system thanks to that and our knowledge of dots based on everything we already learned in this course because that we managed to build this new interaction actually very quickly and just for fun to see the adaptability of dots let's do something funny here so let's take one of our soldiers and let me just duplicate it just to make a nice fun test let's put it over there near that one and on this Soldier let's go down and get rid of the shoot attack authoring again I'm just modifying this Soldier just for a quick test I am not modifying the actual pream and now let's add the Mele attack authoring and set pretty much the same thing so that and let's say 100 okay yep like this let's test and yep there's our Millie Soldier constantly going towards the other one and yep both of them are indeed dealing damage so yep it works this is how easy it is to change behavior when working with a data oriented design all it really depends is just what components are attached to the entity so if you change what components are on certain entity you can easily change its Behavior okay so that's great now let's cover the potential issue with distance that I mentioned a while ago so this working this zombie gets closing up the soldier and attacks that works but now if we see something first of all let's get rid of this testing soldier Okay and let's actually grab another one of these soldiers for testing okay this one going to use this one for testing and on this one let's say that this instead of being this soldier that we have right here this is actually meant to be the tank unit that we're going to create later on this course so let's say this one actually has a big c so over here on the capsu collider right now it has the same size as that but let's say the size is actually super big so let's say it has a radius of four so Yep this is supposedly how big the unit is again eventually we're going to create some tank units which are going to have roughly this size so if we do this and we test let's see exactly what happens okay this is the big one let's move closer and see okay the zombie is coming in and nope there you go that is what is happening the zombie is constantly basically pushing the soldier down it never gets close enough to attack the issue is because the size of the collider if the collider is big enough and the soldier is trying to get within two units but because the collider is too big it can never get there so it's constantly moving towards the same position constantly trying to push it so this is the issue we need to solve we need to make sure that the melee attack logic is not depended on the Coller size so here on the melee attack system on the logic for testing if we should attack here we can't just ask for distance because this will break if the colliders are too big and at the same time you might think okay over here so the solution is me too big but if so then it won't look broken on a smaller C it won't do a melee attack from like a mile away so the solution is to not modify distance here this one is good the solution is to actually have two checks we can have a simple distance check just because it is super simple super fast so let's put pretty much like this let's define a ball for is close enough to attack and it w be close enough if this one is under the melee attack distance okay and then on this one let's just replace not if it is not close enough to attack then Target is too far move closer if not it is closed okay great and then let's define another bullion so bullion let's call it if is touching Target and let's default this to false and then let's check if it is not close enough to attack if not is close enough to attack that means it is not within the attack distance when calculating just distance itself so that might mean that it is generally too far or it might mean that it is close enough to attack but the collor doesn't let it get close enough so over here let's do that test to see which one it is and the way we are going to define whether we are close enough to attack is like I said here is by testing if we are touching the target we're basically going to do a ray cast starting from this unit going towards the target unit we're going to do a ray cast just a tiny bit bigger than the cider for this unit and basally if that one manages to hit the target then we can assume both units are touching each other sove over here let's do a recast which means we need to get the physics World Singleton so let's do that so system API call get Singleton get the physics World Singleton get this one so that the physics World Singleton like this then we're going to grab the Collision world just going pH World Singleton and grab it okay so now we have this Collision world and over here we just want to do a ray cast meaning we just want to do cast Ray and this one takes in a raycast input so let's construct it so raycast input for the raycast input and let's make a new one like this now this one takes a start and for the start we can start on the origin of this unit so let's do local transform let's read the value of the position okay and then for the end for this one we need to know the size the C for this unit now we can either up here add some components in our query for the physics components and use that to get the actual collider but that can become a little bit complex given how we might have different collider shapes so inside of that the simplest way is really just add another field in our melee attack so over here let's just add that so a public float for the collider size yep like this and let's put it on the Baker and pass it in so authoring do col size with that we can now go back here and we just need to get the direction towards the target then multiply that vector by the collider size and eventually we have our end position so let's find find a flow three call it the direction to Target and for this one target local transform sort the usual thing let's grab the position minus this unit's position okay we have the Target and let's normalize it so math. normalize and then down here on the end so the end position is going to be the current position plus direction to the Target multiplied by let's go into melee tag and let's read the C size and Y just like this although like this if we input the exact same C size then it's going to be mathematically perfect just barely touching it so let's add a little bit of an offset just to make sure that we have the actual Collision being tested so let's give it just a little bit of extra space so up here let's find a float for the distance extra to test our recast and let's put it some like4 f so that should be more than good enough so here let's multiply Direction by the collider size plus our small offset okay so that should do it finally we just need the Collision filter now here we could reuse the same thing that we already used for doing a collision filter just for the units but instead just for fun let's actually hit everything let's do that just to be a little bit different and just to see how we can use these super useful constants so instead of doing a bunch of things with M masks instead of that we can just go inside Collision filter and we have two constants we have default and we have zero so zero doesn't hit anything whereas default this one makes the rast belong to all layers and hit on layers so yep we can use this one in the scenario just like this that's our input let's pass it in over here and then for the other one we can either go with this version which will just return a single thing that it hits now this will likely work but when we have a ton of units we might actually have some units close to other units so for example if two zombies are attacking a soldier it might actually hit first the other zombie that is near it as opposed to the soldier so instead of this version let's go with this one that basically has all the hits so that requires us to create a native list of rast hits so let's build exactly that and let's build it up here so we can then reuse it so the native list of raycast hit so The raycast Hit List let's construct it with allocator DOT okay that's our list and now in our recast before we do it let's make sure to clear our list and put an in over here this one has the ref keyword don't forget that just like this okay so now this one will return true if it hits at least one thing then all we need to do is just cycle through this entire list and see if what we hit was the Target that we're looking for so let's see for each for each on the ray cast hit Ray cast hit in the ray cast Hit List cyle through all of them now we just check in here we have the ray castet we have the entity this The Entity that we hit and really just check if this one is a target so let's check if this one equals the one that is on Target on the target component so let's read the target entty if so then we have rast H Target that means we are close enough to attack this entity so here we can set our buan is touching Target equals true and let's break out of the cycle okay yep just like this then down here for the en logic if it is not close enough to attack and is not touching the target then that means the target is too far whereas if it's either close enough to attack or is actually touching the target touching the col if so then we're going to do our regular attack logic so that's it basically we have two checks just a simple distance check and then we have a more complex recast with this we should be able to attack regardless of how big is the size of the collider so let's go ahead and save both of these then over here in the editor let's choose our zombie unit prefab and on this one let's set the col size so let's see yep here we are using the capsu Coller on 0.5 so let's try using that value and let's see okay so there they are this is the one that is actually pretty big let's get close enough and see if that one starts touching the collider and you there you go as soon as it starts touching the collider even though the distance is still pretty far yep it does consider it to be close enough to attack so that's it even with a soldier that has a giant Coller the zombie still does a melee attack as long as it's touching the target cider all right awesome so here let's just get rid of this testing unit and on this zombie unit let's just revert it back so up here on this component let's revert those changes so it has the same amount of health and on the zombie unit let's make sure the prefab is all set up correctly yep it does seem correctly so let's just enable the other zombie unit and this zombie spawner and let's test so yep here we are and a bunch of zombies let's let a bunch of them spawn yep there you go a bunch of zombies now our soldiers go in start shooting so the soldiers attack the zombies but now the zombies also attack the soldiers so they get close enough they start dealing damage and a bunch of soldiers are going to start dying and there you go they're starting to be overwhelmed by all of these zombies and yep everything does work so now the zombies are not just there to catch bullets they can also actually damage our units okay awesome so with this we have two factions that can fight each other so a lot of our systems are already working great now one annoying thing is we still have these soldiers getting stuck while attacking so here if I try to control one of these soldiers I can move it around around okay but if it has a Target nope I cannot move it so let's finally solve that we need to create some move of right logic so let's do that in the next lecture hello and welcome I'm your Cod Mony in this lecture we're going to create a move override component so that we can keep giving orders to our units even while the AI is trying to attack enemies so we basically want to manually override the AI State okay so here we have our units everything works great but when they get close enough to attack as soon as they are within range they start attacking and I cannot move it away so as long as they have a Target then I can no longer control the units we want a way to be able to override that default AI movement but before that let's actually solve one small annoying thing so right now as soon as we h on play right now the units by default they're all going to 0000 0 now that's because that's a default Flo three value later on when we create buildings and set up unit spawning this is not going to be an issue we're going to give the unit a Rel position as soon as they are spawn but for units that we are placing directly in the subscene for that we want them to be able to stay exactly where we dro so let's just quickly solve that we really just need to make one special component that basically only exists for one frame it will set up the unit set up the target position and destroy that component so it only runs once so y let's do exactly that so on the authoring folder let's create a new mon Behavior call it setup unit mover default position authoring and then over here let's do the usual stuff so public struck setup unit mover default position it's an i component data and let's use the classic Baker so we can add it to the unit just like this and if that's it we do not want any data this is really just a tag component so that's it let's save and now let's attach this component to the units placed in the scene the soldier units importantly that's these units on the scene we want this to be an overridden component we do not want it to apply to the prefab like I said later on for units that we're going to spawn dynamically we're going to give them default positions as soon as we spawn them so we only need the special component on the ones that are spawned on the sub scene so up here let's just drag our component that's it nothing else now let's make the system to run it so a new entities I system for the setup unit mover default position system and over here let's keep just our update then let's do a system api. query so for the query we want to set the unit mover to the current position which means we need the enal transform we just need to write it so ref R O then we need the unit mover so that we can write to it so ref RW for the unit mover so we can set our position and finally we just need our component so just ref for the setup unit mover default position so yep these are the three ones let's just do for each including all of these so let's write all of this okay like this so we simply want to set the unit mover so unit mover let's write to it and let's write Target position to be this local transform let's read the current position so that's it super simple and importantly we only want to run this once so let's make sure to remove that component let's use an entity command buffer to do it so entity command buffer and as always let's go system API let's call get Singleton to get the N simulation the Singleton for that one and let's create the command buffer using statea world and manage okay we have the N command buffer so we set up the unit and then we go here and we call remove component and remove this one the setup unit on this entity which means we need the entity reference so let's add with nty XIs and add the entity over here so entity entity and yep let's remove this compon component on this entity so that's it super simple this logic will run just once because we are removing the component and it's going to do whatever setup logic we want now let's add a quick log just to verify so here debug on log and it's actually not the debug inside Diagnostics we add the one inside Unity engine let's do this one say just setup and let's make sure this one only runs as many times as we have units in our seene okay let's test and if it works the units did stay there and over here we can see the setup did only run for as many as we have units all right awesome so this by the way is a great example of how you can do any kind of setup that you want you can just make a tag component and then have a system that goes through that tag and removes that tag at the end meaning it only runs whatever setup you want just once so yep this works it's all fine great so with that done now let's make the move override let's begin by making the authoring component so a new mon Behavior call this move override authoring okay here let's write the usual stuff so public struct for the move override I component data and inside really just want to store a float three for the Target position just like this and now let's make the class for the Baker and add component on this synthy a new move over I and now here let us not write the target position over here on the authoring this one is really just going to be set by code so we don't need to add it here so this target position is what will override the unit mover's position and like name implies this one will be an override meaning we want to essentially Force unit to go to this position but after it's done we want to essentially disable this move over ride and go back into the usual AI so for that let's also make this an I enable component that way we can enable or disable it we enable and set Target position the unit gets there disables this and continues growing on with the rest of the logic and by default enable components start off as enabled but for this one we want to start off as disabled so let's set the component enabled on the Move override on this entity and let's set it to false okay yep just like this let's save and now here in the editor let's add it but we want to make sure to add it just as so unit so don't add it on the base unit or the zombie only the soldiers can have the move over rine so let's add the move over rine and yep just like this okay so now let's make the system that is going to run this so on our systems let's construct a new eye system call the move override system and now here let's keep just our update let's do our system api. query and let's query first of all for the local transform so we know our position and let's read it so ref rro for the local transform then we also need to read the move over right so we at the Target position so ref R for the move override and of course by adding this that means that this query will only run when the move override is actually enabled and finally we just need our unit mover component we need to be able to write to it so ref RW for the unit mover component okay yep like this let's write the for each for all of these okay so now here for the logic it's actually pretty simple first we test the distance towards the target position so math. distance or actually let's use it distance Square from this local transform do value r position towards the target position which is the move override value Arrow Target position yep and we check if the unit is too far so let's actually use the constant that we have on the unit mover system the reach Target position distance squared so if the unit is too far from this distance if so then we want to move closer and if not then we have reach the move override position so if it is too far then we want to move closer so just go into the unit mover value RW set the target position to be the move over the target position and when we get there when we do we really just want to disable the move over right so for doing this we can actually learn something very useful over here to disable this component we can use the system API and call set component enabled so you can do this on the Move override pass in the NTI reference and set it as false so we could do something like this however there's actually a better simpler approach it's actually over here on the query so we can query for ref or refr W those are references to our components but then we also have another special type called enabled and we have enabled ref and enabl ref RW this one basically lets you read or read and write the actual enabled state of that component so if we do enable refr W of the move override this will actually give us the move override enabled component and now with this one we can very easily either make it enabled or disabled so in this case to disable it let's access the value r w and just set it to false and if that's it this one will disable our component okay so just like this this system should be working so let's save it okay so here we are and we have all of these units and if I take one of them and let's look in the inspector in runtime mode and now here scroll down let's see yep here we have the move override and Target position is defaulting to 0 0 yep and we can see that the unit is not on 00 0 so it is not moving towards this move override position and now as soon as I enable this y there you go the unit starts moving starts going towards 00 and then let's see what happens and if there you go as soon as it gets there it sets that one back into false all right so yep everything is working now let's just set this component through gameplay we want to set it when we give the unit an order so over here on the unit selection manager let's go down to where we are doing our right click in order to tell it to move so over here we grab the unit mover and we grab the slide component so instead of setting the unit mover directly instead of that let's get rid of this and let's add with present we need to say with present just in case the move override is not already enabled of move override then here for the component again we are not going to modify the unit mover so we can just replace this with the move override replace all of these references and let's also rename this so here we can use the super useful Visual Studio shortcut to rename and we'll rename all of them that's the move override array and this one is the move override and same thing we go inside the array we grab it we modify the target position and then we save it back onto the array so if that works except over here we are not enabling it so let's also go to the entity manager and let's set the component enabled it is going to be on this entity so let's grab the enti array on the same index set it to true and it's going to set it to true for the move override component okay yep that's it so we assigned the target position correctly and we set the array and we set the move override to enabled which will then make the unit go there and keep going until they get there so that's it let's save okay so here we are let's inspect that unit and scrolling down we can see the move over right is disabled now as I right click yep there you go it does get the target position does get it enabled and when it gets there it becomes disable so that one is indeed working however now if I spawn some zombies let's see so spawn some zombies this one get closer now try to move and nope I still cannot override it now this actually easy to solve we just need one more thing it's over here on the shoot attack system so we have our query which does our a on Logic for shooting the Target and essentially what we want is we want to make sure we only run this logic when the move override is not enabled so up here for our query let's set the option with disabled for the move override meaning this logic will only run if the move override is disabled if it is enabled then just let do its thing when it becomes disabled then runs this logic so y that's really all we need and let's also make sure to also add this on the melee attack system exactly the same thing just like this let's save it okay here we are with a bunch of soldiers and a bunch of zombies get close get them all close enough to start attacking and they get close they start shooting and I click to move and yep it does work I can control them tell them to move they go back they start shooting and everything works all right awesome however in implementing this we broke the melee attacks so we already implement the melee attack logic but right now if I approach one of these enemies if I I get really close and hope the enemies are not attacking the player they are no longer running the melee attack logic now the reason for this is because we implement the move override so that's how we can have some Target either a shoot Target or a melee Target and we can still override movement and when we implemented that we messed up over here the melee attack system we can see here on the melee attack system and basically it's over here on the query so on this query we added with disabled move override this means that units will only do the melee attack if they have no move override which makes sense that's what we want but like this this also means that this query will not match anything that does not have a move override component so this query works great for player units that do a melee attack but does not work well for the enemies because the enemies do not have the move override now to fix this we have two options we can either add some logic to make sure that this really only stops the friendlies from attacking so we could remove the wi over here and simply add an extra logic and check if this entity if this one does have the move override is it disabled we could go with that option or we can simply add the move override to also the zombies both those options work great let's do the easy one of just adding the component to the zombies this might also be helpful later on in case we want to force a zombie to go to a certain place so if we just want to add that component to all them let's go inside our prefabs and to modify all of them let's make sure we want to modify the base unit so on the soldier itself let's go down and on Soldier let's get rid of the move override we don't want that one instead we want to add it to the base unit that way it gets attached to all them so the move override authoring just like this okay that should do it so let's test okay here we are and if we approach zombies let's see if they come to attack and if there you go they are now running the Mele attack logic all right awesome so here we have added a really important move override logic right now with this we have full control of our units we can tell them to move we can tell them to attack and we can override their AI in order to move to a different place hello and welcome I'm your kmy and congratulations on watching through this entire free course video here you'll learn a ton about how Unity dots works and how to make an awesome RTS game you'll learn what exactly is dots how to create entities components and systems and how to make it all super fast with the job system in burst with this knowledge you can now go make some super awesome games that push the CPU to the absolute max if you want to continue this project then you can check out the link in the description the phone course is 17 hours long so 10 hours more than this one it is played across 18 lectures so in the remaining lectures we're still going to learn a bunch of really awesome stuff for example how to make a custom dots animation system build that from scratch we're going learn how to implement a grid symen dots again all data oriented and we're going to implement some nice flow field pathf finding this is a super awesome type of path finding it is absolutely perfect for games like this with tons of units we're also going to learn how to refactor a ton of the systems that we built and make them into super fast bursted jobs then we're going to learn some awesome stuff like how to make a persistent fogar system this one looks really cool how to add some buildings to the game add resource noes super fun ragd dolls and a bunch more so the remaining lectures in the complete course they are full of awesome knowledge check it out to the link description but if you can afford then that's fine I hope you learn a ton from this awesome free video here you learn more than enough knowledge to start applying dots to your own games now you have knowledge of this super awesome tool that will help you whenever you encounter any kind of performance issues also remember how you don't have to go fullone dots or fullone game objects you can make some both so you can keep making games mainly with game objects and then use dots just for the performance intensive Parts remember how dots is really just another tool in your tool belt and now you know how to use this really awesome tool so definitely make sure you use it wisely all right so I hope you learned a lot from this free video go ah and like the video and subscribe if you haven't already thanks for watching and I'll see you next time
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.