Creating Multiple Enemies : From Prefabs to Entity Spawning - Unity DOTS ECS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone today we'll look at how we can  create multiple enemies for our tower defense game so we'll be covering throughout this video  the concept of the entity common buffer and what is a structural change and we'll also have  to discover what are tag components and it will give us the opportunity to speak about the  IEnableComponent and we'll also have a look at the ordering of systems with the attributes update  after update before and update in group let's get to it as you can see I went ahead and copied the  third folder the spawning folder from the GitHub repository linked in the description below and  I've imported it into my project for this tutorial series the folder structure remains the same and  if you go to the spawning scene you will see that the spawning sub scene has a similar layout as  the previous episodes we have the way points which are defined on the scene so if even if we  can't see them because there is the backing only autoing entity we've seen in the previous episode  the waypoints are defined below a spawner and the spawner will define what prefab it will  spawn and at which rate it will spawn it so if I put a spawn interval of 0.2 and enter play mode you  can see that I'm spawning several entities every 0.2 seconds and that they are running in circle  around the waypoints so let's first take a look at the baking workflow let's have a look at how  we can bake this information into an entity for it to spawn the enemies every few seconds as you  can see in the spawner autolink script we have exposed a game object for the enemy prefab not  an entity a game object we also have exposed a float field for the spawning interval and we get  the path that the entity will follow through the children of the spawner game object then in the baker  first thing we get as usual the baking entity so the entity we will be creating from this game  object in the sub-scene which is our spawner this time we use the world space flag because we  want it to have a location in space but we don't care about moving it so we don't need the  local transform component then for the spawning we add the spawner data which is a normal   IComponentData the difference here is that we are storing the enemy prefab as an entity field  and we are also storing the next the spawning interval and the time until the next spawn so  these two Fields can be populated as usual in the Baker we populate them from the authoring  value we have in the spawner aling and for for the entity field in the spawner data we need  to actually do another get entity on the game object that represents our prefab that will  tell the Bing workflow that we also need this game object to be converted to an entity and  moreover it will tell it to be converted as a prefab and for this one we actually want  our enemy to be able to move after we have spawned it so we will use the transform usage  flag Dynamic and finally we store the path for the entity to follow on the prefab itself  on the prefab that we will spawn using the waypoints and the dynamic buffer as in  the previous episode now that we have backed our entity we can have a look back at the  editor if we look at the entity hierarchy we can see that we have our subscene and within  that subscene we have two entities the spawner itself and the pass follower which is the  prefab we defined on the spawner entity if I look at the spawner we can see that this  entity is a prefab because it's highlighted in blue and if we look at the inspector for that  entity we can see that we have the tag component prefab tag component is a normal component  but it doesn't contain any data so if we have a look at the definition of the prefab tag  component which is defined by unity entities we can see that it's a normal struct prefab  that implement the IComponentData and it doesn't contain any information this  is useful for when we want to distinguish between different entities that have the same  data but we want to group them in different categories that can be used for instance for  State machines or other category based processing this tag component is a bit special  because it's defined by unity and by default is not considered when we have entity queries  so if I look at the PF system we had in the previous episode when I'm doing my system API  query it will not return any component that have these information or these components  if they have the prefab component if I wanted the system to also run on prefab entities or  entities that have that prefab tag component I would have to add the with option and use  the entity query option include prefabs so by default this is not the case I want my  system to run only on the actual entity and not on the prefab itself as I said the tag  component can be useful in use cases like State machines but if a tag component represent  a state of a state machine it means that we'll need to add and remove the tag components based  on the state of our entity and add and removing component is what we call a structural change  without going into too much details if we have a look at the way we store the data in ECS  we have already discussed about the notion of Chunk so if I take a color code for the  data let's say orange for the transform red for the health and blue for another kind of  data this set of of data constitute what we call an archetype and that archetype is stored  in memory in a chunk so an area of memory where we store all the entities that have all of  these three components if we now add a tag component so let's say we have two entities  are not really stored like that but if you want more detail on the layout you can have  a look at the other video I made on the topic so if one of these two entity has a new data that  is added so let's say we have a new data type which is green then it means that it doesn't match  anymore the archetype for that chunk for that chunk of memory so this archetype is this chunk  of memory is just for the archetype red or orange and blue so that means I need to create another  chunk of memory somewhere else for me to be able to store a new archetype which is the orange red  blue and green and take that entity move it from the chunk of memory it was in originally and put  it in the new area of memory that I allocated just for this archetype as you can see a structural  change involves a lot of operation and it also involves allocating new memory or at least copying  some memory in the worst case scenario it it means allocating new memory to create a new chunk of  memory for the new archetype So to avoid that we have the option to have another type of tag  component or a more General sense of the term another type of component which are the IEnabledComponent we can actually have a look at one of them right here in the inspector so if I take my  prefab pass follower I can see here that I have another tag component because it's in the tag  section which is a simulate tag component and there is a little checkbox next to it so I can't  click on it because I'm not in play mode and we can see that we have this simulate component on  every entity we have so if we want to demonstrate that we can take the spner for instance pick a  higher value for the spawning let's say 1.33 and if I go back and enter play mode you can see  that our sponner is active while simulate is true and I'm spawning a new entity every 1.33  seconds as you can see in thearchy if I disable the simulate IEnabledComponent the spawner is  no longer spawning any entities if I enable it again I'm spawning new entities again and to  be clear an IEnabledComponent is not necessarily a tag component like we said a tag component is an  empty component that serve only to identify a set of we want to operate on with a specific system  an IEnabledComponent can contain data it can also be useful for State machine to store  actual data related to that particular state for instance but there are two different concepts the  tag component is an empty component the IEnabledComponent is a component that can be enabled or  disabled without structural change whereas the tag component if you want want to add or remove  it it needs a structural change okay so now let's have a look at how we actually are  spawning those entity in our system so going at the spawner system we can see that like in the last  video we have a partial struct that implements a ISystem and this time we are actually using the  on create method because for us to spawn the entity we will need what is called an entity  command buffer to perform structural changes you can either do it through the entity manager  or you can do it using an entity command buffer an entity command buffer will allow you to  postpone or to delay the execution of your structural change to a certain step in your  frame or to a a certain point in your frame so that allows you also to queue up commands in  parallel systems so you'll see that in a further video for a simple use case like that we could  also have used the entity manager to directly spawn the prefab but I want to demonstrate the  entity command buffer in this video so Unity defines a few systems that already allow us to  use entity command buffers I've listed all of them here and and today we'll use the begin  initialization entity command buffer you can actually have a look at where they are exactly if  you open the window entities systems and if you have a look at command you will see all the  entity command buffers or all the system that expose entity command buffers so as you can  see the begin initialization entity command buffer is the very first command buffer and if I  remove the filters you can see it's actually the very first system that execute in the loop  so that's the first system of your player Loop going back to the code we can get the  entity command buffer through a singleton so a singleton entity is an entity that there  is only one of in the world of ECS and we get that entity to create the command buffer  using the world unmanage as parameter this will give us an entity command buffer next  in our system like before we use a system query to get the components we need for this  one for this one I've added the with simulate IEnableComponent component tag so that's how  I demonstrated we can stop the spawner from rning new entities in the inspector window  or in the editor and then what I do in the system is that I compute if I've reach the next  time to spawn an entity and if it if that time has come we can create a new entity using the  entity command buffer instantiate and passing in the prefab entity we want to duplicate or  to clone to make a new live entity for our game what we need to be aware here is that  since we are using an entity command buffer we are not really creating the entity yet what  we are creating here is is a temporary reference so if you were to debug The Entity index we  have here you would actually get a negative value so it's not valid entity but it allows us to  use that entity reference with a negative index in other entity command buffers that we have  to do to create our entity so in this example I'm using another entity command buffer command  which is a set component on that entity that I just created so for now it's a temporary entity  and I'm actually setting the position to be the position of my spawner so the entity is spawned  at the location of my spawner and then I'm using another entity command buffer to add the Waypoint  buffer to my instantiated entity and I'm copying all the waypoints from my spawner to my entity  that I just spawned so that it can follow the path for itself if we go back to the top of the  system we can see that in on the on create method we have the require for update begin entity  or begin initialization entity command buffer system singleton meaning that this system for  begin initialization entity command buffer system that's a mouth full needs to be created and running  before I'm actually updating this system so I need this entity to exist for me to be able  to create the entity command buffer that's why I have the require for update here in the on create  method and the last detail I want to point out is that I'm using an attribute here update after  so there are three attributes that allows you to control where the system will be updated in  your player loop we have the update after which will tell the system to update after another  system or another group like here I'm telling the system to update after the transform system  group I could also have an attribute to say Okay I want the system to be updated before and in  that case the system would have to be updated before the system I pass in in the attribute or  I could say Okay I want the system to update in a specific group so in that case it needs to be  a component system group here I'm saying that I want this to update after the transform system  group so that if I'm to spawn an entity based on the location of something else in that case the  spawner even if it doesn't move I'm sure that the entity that I'm copying the transform from  has been updated and one thing you need to be careful also is so if I look at the system if  I were to create an entity after this system but before the presentation system group the  transform of the entity I just created could still be 0 0 0 so if you ever spawn an entity  and have it rendered or Flicker at the world origin it's probably because your system order  is not correct but since I'm using the begin initialization even if I'm viewing the command to  instantiate the entity after the transform system group the actual entity will not exist before the  next frame so it will have time to be updated by the transform system group before being rendered  you also need to be careful about which command buffer you use or which command buffer system  you use when you queue up commands because for instance if you were to create an entity command  buffer for the beginning initialization where you que up a command to destroy an entity and  then you have another system that for that same entity que up a set component in the end  initialization system for instance in that case The Entity would be destroyed before the command  for setting the component would be executed so this command would fail my advice on that is  to pick a set of command buffers and always perform the operation in the same order so for  me for instance I create my entity in the the begin initialization system I usually set the  components or create or add components on the end initialization system and if I want to  destroy an entity I either do it in the begin simulation or in the end simulation entity command  buffer systems I'm always sure that the end or the destroy command basically will happen last next  we will put in practice what we just learned today and add in a bit of physics to be able to place  Towers on a specific spot on the terrain and as usual if you like this content don't forget to  like and share the video if you want to support the channel you can use the asset store link  affiliate Link in the description below or like Neil did thank you Neil you can support us on  coffee also either with a single donation like Neil did thank you again or through monthly  subscription I'll see you in the next video
Info
Channel: WAYN Games
Views: 714
Rating: undefined out of 5
Keywords: ecs, game development, Unity DOTS, Unity ECS, Data-Oriented Technology Stack, Unity Game Development, Game Programming, Entity Component System, Burst Compiler, Job System, ECS Architecture, Unity Tutorial, Unity Asset Store, unity dots tutorial 2024, Unity dots tutorial, game dev, how to make a game with unity dots, unity data oriented design, unity ecs 2024, unity dots 2024, untiy ecs tutorial 2024, dots, unity ecs baker, Game Development Workflow, ecs baking
Id: wpuBGPqa4z8
Channel Id: undefined
Length: 21min 8sec (1268 seconds)
Published: Sat Mar 02 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.