Mastering Unity DOTS: Configuration Guide and Fundamental Features

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello everyone today we'll cover three new topics around the new component type the performance with the burst compiler and the baking workflow. And somewhere in the video I will share with you a quick tip to make your code cleaner in systems for the components we discover the dynamic buffer IBufferElement and introduce the internal buffer capacity. Around performance we'll talk about the burst compiler and how you can see your burst compiler performance in the profiler. We'll also for the Bing workflow cover Bing departy concept and Bing only entities and we'll add in a bit of local transform knowledge with the local transform and the transform helpers. So as usual you can get the full tutorial code in the GitHub repository linked in the description below. The folder structure is the same as for the first episode we have the second episode folder containing authoring components, components (ECS components) mono behaviors, no prefabs, some resources the Scene folder and the systems folder. So once you've imported that into your project you can go to the scene folder and double click on the PathFollow scene not the subscene but the scene. It should open up this scene in the hierarchy and if you have it closed like that you can open the subscene by clicking on the checkbox and unfolding the content of the subscene by clicking on the fold out arrow. As you can see here we have four game objects which are called waypoints which match all of these the small spheres in the scene if you enter play mode you will see that the entity follows the path and reach each way points and once once it has reached the last way point it circles back and keeps running around in circle. So how did we do that exactly. If we go back to the folder structure and look at the autoing component which is referenced on the game object you can see that we have in the code a scriptable object reference for the movement speed this scriptable object is very simple basic skip table object containing the speed field and we also have a list of transforms which is an empty list at the beginning and we populate it through the inspector. In the baking itself as you can see here we are still getting the baking entity so the entity that we are building based on that game object in the subscene. And we are using this time the transform usage Flags dynamic because we want that entity to be able to move in the world and be rendered. Next we look if we have any way points into our path to follow which is the property we have set up in the authoring component and if we do we create something that is called a dynamic buffer So since ey component data can't store list type are restricted to bitable types like we've seen in the previous video we need to have a different approach if we want to have a list of values in our entity or associated to our entity and for that we use what is called a dynamic buffer and to define a dynamic buffer we need to create another type of component so it's not an IComponentData but it will be an IBufferElementData if I click on the way points you can see that we have still a public struct which is called Waypoint but this time I'm implementing the interface interface I buffer element data and I'm describing a single value so this represent a single element of the list which is contained or which is defined as the dynamic buffer. Here we have an attribute that is called the internal buffer capacity it's a bit more advanced but you can keep in mind that it allows you to control the number of element you want to associate directly to your entity or in the chunk, in the memory chunk if you want there is another video I made about uh how the memory layout is handled for ECS and explain what's the difference between game objects and entities so you can have a look at that after this video if you want more details about the internal buffer capacity. Going back to the PathFollowAuthoring once we have created the dynamic buffer it's empty so we need to populate it with all our waypoints and for that we iterate through all our pathToFollows transforms and create the new way points to add to the dnamic buffer. Next for the entity to move we need to define the speed for that entity so the speed is created same thing as an IComponentData this time because it's a single value it's not a list of values and we put populate it with the movement speed that comes from our scriptable object in the autoing component. Now since this is a scriptable object it's an asset and when your entity or your baked entity depends on an asset if you want to update the entity representation in the ECS world when you update that asset you need to declare a dependency from that entity onto that asset and to do that we use the depends on method and we just pass in the assets that this entity and this Baker in particular will depend on meaning that every time we modify the scriptable object it will update the entity to see the dependency taking effect we can go back to the editor and enter play mode and if I select the slow scriptable object which is set on my entity look at the console if I modify the value five you can see that the entity is moving faster and that I've logged that the backing of the pathFollower was executed if I update it again let's say put it at two again it's slowing down and it's still updated now there is a little caveat to that we need to be careful about here if you look at the sub scene it's opened I can close the sub scene and still view all of my entities and basically they are only existing as entities now no longer as game objects if I want to update again my speed through the script table object which my entity depends on I can still update it but as you can see the entity is not moving faster and I didn't put any additional log saying that the baker was invoked for the dependency to be detected on the scriptable object you need to actually save the asset for it to trigger the baking on closed subcene and to save it you can either go to file and save or press Ctrl+S and if I press Ctrl+S as you can see the entity is moving faster and I did log a new entry in the console saying that the baker was executed I can stop now if we have a look at the project and look at the subscenes we can see that we define the path through the way points as game objects and if you look at the entity hierarchy in the runtime view you can see that we see our way points in the runtime world this is because these entities are baked when in fact we don't really care about them because the path has already been saved in the dynamic buffer of the pathFollower. So what we can do to remove them from the runtime scene is to add the component = BakingOnlyEntity so if we select all our way points and add the component BakingOnlyEntity save the subscene and if we look at the entity hierarchy we can see that the entities for the way points have disappeared but we are still okay because the path itself has been saved in the dynamic buffer of the pathFollower entity and of course if we enter play mode the entity still runs around like previously and if we continue and finish the baker you can see the last thing that I'm doing is just adding a next path index which will allow me to know at which waypoint my entity last went through and set the next waypoint as the target for the movement. Speaking of movement we can have a look at the pathfollowSystem. So as for the previous episode we have a simple partial struct implementing ISystem and in that ISystem we are implementing the OnUpdate interface again we are not implementing the on create OnDestroyed or even the OnStartRunning OnStopRunning because we don't care for this example and same kind of work that we did last time we are querying through the SystemAP.Query all the components of entities that we want to act on we have the speed as read only again the local transform as ref read/write because we want to modify the local transform value which represent the position of our entity relative to its parent so if it has no parent it's the world position the next pass index again read/write to set the next Target or the next Waypoint uh to to go towards and lastly we can query directly the dynamic buffer as you can see we don't have any ref read/write or ref RO for the dynamic buffer because by default they are considered to be accessed as read and write so you don't have to put in the ref before calling the dynamic buffer. Here I'm using different syntax than the previous episode because as you have seen in the previous episode when we want to access information we don't actually get the component but a reference to the component so we need to call reference to the component and then say we want the value inside that component either in only or in read and write to avoid repeating this dot value RO or RW we can use this syntax saying okay for readon we declare a ref readonly component and call make it equal or assign it the actual reference of the component from The Entity and if it's for read/write access we can use the ref component again without the read only of course and do the same thing this allows us to use for instance the transform directly without having to call transform rw. value RW which makes things a bit more clear in the code. For the actual execution of the code it's pretty straightforward I'm checking if I've reached if the position of my entity has reached the position of the next Waypoint and if it's the case or if I'm close enough I'm setting the next waypoint in the list of way points to be the next Target for the entity to follow and finally I'm moving the entity by picking the direction based on the current position and next Target position moving it along the Direction at the given speed and finally I'm making sure using the transform helpers that the entity is actually looking towards the direction it's movin. That's it for the system one thing I didn't cover is at the top here if you've seen we have an attribute that is called the Burst compile attribute and that basically means that this method and the execution of the code inside that method will be compiled using the burst compiler. The burst compiler is basically what converts your C# code into machine code and it has some specific platform to optimization and it allows for instance to use Loop vectorization which basically is using SIMD so single instruction multiple data with you to basically process the code even faster. We can actually have a look at that in the profiler so if I go back to the editor you can open the profiler in Windows > analysis > profiler I've already opened it here clear this one and if I start playing pause the game pick a frame I can look down here in the timeline so I can actually search in the hierarchy for my job and type in path here and pick the default world because we can have multiple ECS World we'll come back to that later and if I look at the pathFollowSystem I can go back then into the timeline and it will have highlighted it and here we can see in the timeline I actually have to zoom quite a lot here we can see that we have our pathFollowSystem you can see also that it's in green and not in blue like others we have some other green timeline representation so if it's green it basically means that the code executing or this method is burst compiled we can check that actually if we stop play mode and you can look at the jobs here and you can actually disable the burst compiler by clicking on burst enable burst compilation this will have disabled the burst compilation and if I clear the profiler enter play mode again pause pick a frame now I can see that this is no longer green uh sorry it's not this one I look again for my system and here I can see that it's no longer green so basically it's only compiling normally without the bur compiler and you can actually see that the other jobs or other systems are no longer first compile either so this option here disable the burst compiler all together so we won't have any burst compiled system if you want it just for your system to be not burst compiled you can remove the actual burst compile attribute and it will no longer be burst compile one little little teaser for uh upcoming episodes you can see also below here you can unfold the job and you can see here all the threads that would be able to use to execute code in parallel and we'll see that in a later video. Next we'll learn how to spawn multiple enemies using the entity command buffer learn what is a structural change and see how we can organize our system and the execution order using some attributes if you enjoyed learning with us today don't forget to like and share the video you can also support the channel on Ko-Fi with a simple donation or a monthly subscription or if there is any assets you have your eyes on you can use the affiliate Link in the description to purchase it and it will support the channel also thank you for watching and see you in the next video
Info
Channel: WAYN Games
Views: 2,484
Rating: undefined out of 5
Keywords: Unity DOTS, Unity ECS, Data-Oriented Technology Stack, Unity Game Development, Game Programming, Entity Component System, Burst Compiler, Job System, Collections Package, ECS Architecture, Unity3D, Unity Tutorial, Game Development Workflow, Unity Asset Store, game development, unity dots tutorial 2024, Unity dots tutorial, Unity job system, game dev, how to make a game with unity dots, unity data oriented design, unity ecs 2024, unity dots 2024, untiy ecs tutorial 2024
Id: Z5CMGm6lmDQ
Channel Id: undefined
Length: 33min 39sec (2019 seconds)
Published: Sat Feb 17 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.