EPIC BATTLE Marines Vs Zombies in Unity ECS!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to check out a really cool bottle of Marines vs. zombies built entirely in unity ECS we have a lot of Units on-screen animation a eye movement and lots of interactions between systems and components we're going to view how all of this works let's begin [Music] hello and welcome I'm your code monkey and this channel is all about helping you learn how to make your own games with nf2 torrents made by a professional indie game developer so if you find the video helpful consider subscribing alright so here we are in our scene just a bunch of Marines sitting here waiting for the zombie apocalypse almost everything is built using unity ECS and over here are some zombies being spawned here they come and as they approach the Marines find them as targets and properly start shooting I can spawn more Marines found left clinton there we go every time spawns one and the number of zombies being spawned is constantly increasing after a while zombie start coming from the side and they stop coming all over as I said most of this is built in pure easiest and if I pause the game you can see over here on the hierarchy there aren't many things some of the things are the default effects that I haven't yet converted into is yet but most of the units and behavior are handled by pure ecs and there are no mana behaviors in here so the hierarchy looks mostly empty regarding the units however here on the entity debugger here you can see a much different picture with a bunch of entities all of them in a bunch of chunks and a bunch of systems doing all the work so here is our scene and there's all the Marines constantly fighting all the zombies and they keep going and I can spawn some more and eventually they won't be over up all right so this is our very nice demo scene we have two types of Units Marines and zombies the Marines are all looking for their target and once they get in range they start leaning shut there are lots of extra effects to make the whole scene seem very nice and as you can see the more they are spawned the more the circle closes in and soon enough they won't be overrun ok so this is a great demo scene now let's check out the code that makes all of this work now this video is mostly intended as a demo of what can be done with ECS so instead of a step-by-step tutorial I'll go over a brief overview of how each system works if you'd like to see more in the up step by step tutorial of any of these systems then let me know in the comments also if you have absolutely no idea how easiest works then start by watching the video on getting started after watching that video a lot of what I'm going to show here won't seem very familiar now there are many systems that work in order to make this scene work we have spawning animation ai and movement using a lot of systems and components there are also a handful of systems they use normal game objects as he saw mostly they are things like the shoot flash the fighting body or the blood particles which can certainly be done in ECS I just haven't poured them over yet so let's go up here to start off with the simplest system here we have just our main bootstrap script and here on the start function we initialize things and we have a function to spawn myrin another one to spawn a zombie so here is the spawn myrin function we just spawn it using a certain archetype containing all these components then we set all of the values for those components and the zombie also has a lot of similar components one of the main different are the attack components so this one has the zombie tag and this one has the marine tag and if we check it out you can see those are completely empty components really just tags the other components are these related to the animation system over here related to the quadrant and targeting system then in a very simple health component a component deal with how much the marine should shoot a simple move to component a component to handle the various animations that should be played any simple translation position component so that's a way to spawn a marine and a zombie and down here on a simple monobehaviour update we are simply handling our camera and then D zombie spawning here are just some timers and some spawns on me count that increases over time so here I can easily change this and all of a sudden amount of zombies gonna be spawned and Here Come a lot more zombies and very soon these guys won't be overrun even if I spawned quite a few more okay so that's our spawning system it simply checks over time and constantly increases the amount of zombies that get spawned and the components as you saw were different so we can pause and look at the entity debugger and here we can view all the chunks and if we click on a simple entity you can see that this one is a marine target range of a hundred playing these animations and in this position so the spawning in the composition of the entities is quite basic another simple system is the movement over here as you saw we have a move to component this component simply has a boolean to decide if he should move in a position any moves B and then down here there is a system system runs on entities that I've been moved to translation and the animation components and we simply use it to do a simple distance check in order to move and play the correct animations so again very simple stuff then for the animation system which is probably the most complex part of this demo the animation system is essentially the same system I've gone long ago but converting to ECS so it's essentially the same thing that I've used in all of my videos the way the system works is by having one mesh per frame of animation and a component that holds data to select which mesh that units should use in order to actually display the mesh I have this component system right here essentially how it works is by cycling through all of the entities then it grabs the correct mesh based on the current frame of the animation and the animation type and direction then it simply draws that mesh into the current translation position so the whole drawing is done in here rather than using the basic render mesh now the core of how the animations work is by essentially keeping a list of vertices and UVs so here on the animation system I have a struct for each one so each one has four vertices and essentially four UVs and each body part gets displayed in a single quad so the head is a quad the body is another quad the hand another quad and so on then all of those quads come together in order to make a single frame of animation and as soon as the game starts I essentially pre calculate all of the meshes and store them in a list so in here I have a dictionary that for each animation contains a list of mesh each mesh for a single frame of animation I've done a lot of testing in order to figure out the various methods for playing the animation and this is the best one I found with regards to performance when the game starts everything is pre calculated and then during play mode it simply grabs the correct mesh so back here on the mesh display as you can see we are simply grabbing the mesh from the mesh list which is based on that animation and that direction and the current frame the current frame is increased by a different job in here as you can see it's very simple just go through each entity that contains the accountant data increase the frame timer which increase the current frame here in the scene view we can go up here in order to enable shaded wireframe and you can see that each of them is indeed made up of quad so we have the head quad the weapon quad the foot foot and a foot body and so on so this is how the system works essentially we pre calculate the mesh containing all of the quads and then during runtime we simply select the correct mesh here if we don't look at the entity debugger you can see the entity count constantly increasing and here is the skeleton mesh display system which as you can see is increasing over time so here with 200 MTS it's taking roughly one millisecond so right now this is the approach that I found best for performance I've tested several ways of showing the animation like dynamically creating the meshes but keeping them cached works best this way I can have several thousand animated meshes and everything works over here on the display system there are a two performance bottlenecks that I need to improve one of them is getting the mesh list in order to grab the correct mesh this one is done by finding the mesh in a dictionary which takes quite a while to calculate so this one is quite simple to fix we can simply use a normal array and currently the index and that would be quite a lot faster and the other bottleneck is dealing with mesh itself here as you can see all this is running on a normal component system so none of this code is being multi-threaded it would be great if it was possible to update a mesh inside a job and maybe keeping just one mesh and modifying it instead of keeping a separate mesh but since mesh is a reference type it cannot be used inside the current job system also it would be very useful if we could access the graphics API in a multi-threaded environment I tried writing some multi-threaded code in order to draw the meshes but the graphics API must be called on the main thread so right now this entire system is not benefiting from the job system the more entities we have the more cycle this function goes through and the longer it takes so that's how the mesh and the animation system work so about pre calculating all the missions and then simply selecting them in order to match the correct frame of animation then there's also the quadrant and targeting systems which work very much together however in this case since EC s is so insanely fast I'm not sure if the quadrant system is really necessary if the map was a lot bigger it would probably make more sense but for this little demo not so much necessary but still here it is now a quadrant is essentially a portion of the map in this case it's simply a square now down here I have a simple debug function which won't draw each quadrant as I pass the mouse over it so let's test it so here we are with gizmos enabled and as you can see as I pass the mouse over this essentially what a quadrant on equivalent system is this system is designed in order to make it easier to look for targets since you don't have to look through the entire entity and list so in here for example in this quadrant you have this unit this unit and this unit so if these were all looking for targets they wouldn't look for targets that were in this quadrant all the way over here they only check the neighboring quadrant so the entire goal is to put units into buckets based on position so when this Marine is looking for a target he's not going through every single entity on the map rather only the ones in the quadrants nearby so as you can see only when they enter that quadrant does he finally start to target them the benefit is to limit the number of units you have to search through in order to find the closest so this marine here will never ever ask for the position in order to see if this one is equal to zombie it only looks for the ones nearby again as I said since the way that this is done works really fast so in this case the quadrant system is not absolutely necessary but if the map was massive you can see how this marine would not want to look for a zombie that would be all the way over here so the bigger the map the more important it is to have a sort of quadrant system so here let's go over a quick overview of how the system works now this is certainly a great system and something I want to cover more in depth in another video since it involves some really interesting logic each entity as he saw contains a quadrant entity component this is how we define which entities won't be managed by the quadrant system it simply contains the type so either a marine or a zombie now inside the quadrant system we are working with a native multi hash map which contains an int for the hash key and the quadrant data for the various values as you can see the quadrant has the entity the position and the quadrant entity that is in there this native container lets you store multiple values inside a single heat so inside a single position key you can have multiple quadrant data so that is how you have multiple units inside the same bucket then this function in here generates a key based on a certain position it just some math based on a certain sound size and ensures that units within a position near that cell always return the same key so entities in the same quadrant won't have the same hash key added to it now there are multiple jobs in order to make this whole thing work the first one is this one to set the quadrant data on the hash map so what this one does is it cycles through all the entities that contain a translation and a quadrant entity component it gets the position hash map key and simply adds a new quadrant data on that hash map key so here we are just positioning all the entities into their correct quadrants after we set all the entities into their quadrants then we have define causes target job this one cycles through every unit and it tries to get the closest target on the nearby quadrants so you start with the center quadrant then the one to the left right and so on so you check all nine nearby quadrants and then at the end we have a causes target entity now in here in order to benefit from the insane benefits of bursts instead of adding our hash target component we simply store the units and their targets into a native hash map and after finding the closest target job we have another job in order to set the target this one does not use burst since it uses the entity command buffer and we simply use it north to the has target component with the causes target I've done a video on how to find the closest target so check that out to see a more in-depth look into how this logic works and down here on the update we are simply preparing all of our data and scheduling our various jobs so first we position them in the hash map then we cycle through all the units are to find it closest and then we add the component to the causes turret again here we are in our scene you can see the highlighted quadrant and down here on the console you can see how many entities are inside this quadrant so this one has 6 1 2 3 4 5 6 yep there are 6 and over here the zombies are coming so now it's got 0 and now it's increasing 1 and so on and as you can see as soon gets one these guys start looking for a target on this quadrant so as soon as they enter they start getting shot and if we look at the entity debugger you can see this entity for example has the historic component which contains the position of his target and the entity field again check out the video on finding the closest target in order to get a more in-depth look into how all of this works so once the unit has a has started component then we run another system over here is the marine target zombie system as you can see it's running on every entity with translation the plan animation component has target component and the Marine shoot so he checks if he can shoot if so he plays the shooting animation and he shoots the target entity now the shooting and cousin damage was an interesting problem to tackle doing AI in ECS is probably the most difficult thing to wrap your head around right now in order to be super fast it's really a requirement in order to use memory sequentially that's essentially what the entity chunks do grabbing a piece of random memory for the target Hertz things so we need to minimize it as much as possible so over here my approach has been based on a queue of actions so whenever the Marine should say target he doesn't directly interact with the zombie in order to cause some damage whether he just in queues that action so that way this system for shooting the zombies runs in parallel and then here I have the queued action system which is running on just a simple component system and he goes through all of the cute actions so right now the only action is a marine shooting a zombie so here this code is running on the main thread and it's what finally actually cause damage to the zone so you get the positions for the marine the zombie then we have some bonus effects running on single threaded code all these are not yet port EECS so you can see here how you can mix and match use some systems in ECS and some systems with normal game objects then here we grab the zombie health we ask the entity manager in order to get the health component for the zombie entity once we get it we'll reduce the health by the damage amount that is stored on the zombie action and then we test if he is dead then we spawn a fine body we destroyed the entity and we the component has target from the marine entity if he still has health then we simply update the zombie home so here as you can see for the AI we separated into two systems so first we have the Marine he does all of his data and shoots the zombies that he has as targets he in queues a specific action into a cute actions native queue then after this system runs with all of the marine entities we run our cute action system which goes through all that cute action queue and we do everything we need to do in order to handle the interaction between the marine and the zombies obviously the biggest issue is in here we are using a component system so this code is not Java 5 at all all of this runs on the main thread that means it could potentially become a performance bottleneck however the number of actions that happen every single frame is going to be quite small so in most cases I think this specific pattern would work well in an ECS game again making AI in ETS is a very tricky subject so perhaps this is not the absolute best way of doing things I continue learning as I go along and for now this seemed like a good approach so this is the complete simple demo scene our Marines are here standing around these zombies are being spawned and they move towards them as soon as they get close the quadrant system works in order to find a target for each of these Marines the animation system is working as you saw each animation frame is a mesh and we simply selected on every single frame the zombies keep spawning after a while they start spawning from the sides and they come from everywhere more and more gets fun more and more keep coming and here you can see our stats and right now you can see that this whole scene with all these zombies all these units is currently running at a hundred frames per second and again a lot of these effects are not using ECS so this could be improved even more and more and more keep coming and with all of these zombies all of them working independently all of them have their own AI their own code there aren't things and we're still running at 60 70 frames per second and they all keep going to keep getting a run and again I can still click in order to spawn a bunch more so spawn more in order for them to breathe a little and if they are pushing the Mac everything is working quite nice so as you saw there are still many years that can be improved but this already looks very nice for a pure ECS game and clearly demonstrates the performance benefits also I'm still learning easy as myself so what I've built here might not necessarily end up being the best practices for a pure ECS game as time goes on and more people play around the easiest the best practices will start to emerge so hopefully you've enjoyed this nice little demo of what can be done with ECS it's not necessarily a more difficult way it's just a different way of thinking about how to write code and how to do things as always you can download the project files in utilities from inti code monkey comm if you liked the video subscribe the channel for more ent tutorials post any questions there have in the comments and I'll do my best answer them alright see you next time [Music]
Info
Channel: Code Monkey
Views: 34,086
Rating: undefined out of 5
Keywords: unity ecs, unity ecs example, unity ecs demo, unity ecs animation, unity tutorial ecs, unity ecs tutorial, unity ecs 2019, ecs unity, ecs unity tutorial, unity pure ecs, unity ecs job system, unity dots, unity dots tutorial, unity dots ecs, unity pure ecs tutorial, unity dots demo, unity 2019, unity 2019.1, code monkey, brackeys, unity tutorial, unity game tutorial, unity tutorial for beginners, unity 3d, unity 3d tutorials, unity tutorial 2d, unity2d, unity3d, unity
Id: fTw_fXsvC6I
Channel Id: undefined
Length: 18min 47sec (1127 seconds)
Published: Sun May 19 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.