Converting your game to DOTS - Unite Copenhagen

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone how are we doing yeah whoo Wow all right then I'm glad I paid those guys so we all just ate lunch probably some turkey and now we're all in a nice dark room and ready to take a nice soothing nap fantastic all right so my name is Mike GOG I'm an evangelist at Unity Technologies and today we're gonna talk about converting your game to the data oriented technology stack or dots all right it's a pretty big topic here at unite it's a pretty big topic for unity so let's dig on in so what are we gonna talk about well we're gonna talk about what dots is very briefly we're gonna talk about why we want to do this when we want to do this I think that's a very important topic and then probably the most important topic how right that's stuff we all want to see now before we start I just wanna make sure we're all clear about this term dots right we threw those term dots out a lot fairly recently and I want to make sure we all kind of get what that means so you may have heard us talking about the the job system the C sharp job system the entity component system which we call ECS burst compiler project tiny or dots runtime or things like that and all of those things combined is this toolkit called dots so dots isn't any one thing it's a collection of a bunch of different tools which all sort of fall under this umbrella now that being said you know most of the stuff we tend to see and talk a lot about is this thingies yes we're gonna look at a lot of that today and how these things play well together real quick just raise your hand have you anyone here tried to implement some ECS code using unity CZs in your game or project fantastic how many of you found it really easy to do sorry let me rephrase how many of you are liars no I'm just teasing I'm just teasing right but well that's one of the things we're gonna talk about is this sort of mental change from the way we're used to thinking about things that makes this stuff work can make it very frustrating to begin with but then really awesome once it finally clicks so let's look at what some this stuff is so first thing I want to kind of address is why do we do this now we have a lot of proof points you've seen a lot of stuff I'm gonna cover it again you may have seen this before but bear with me here so this we're just gonna pretend this is a highly simplified version of what your memory looks like on your computer when you're using object-oriented programming right c-sharp and things like that stuff is scattered all over in memory and anytime your processor needs to process any of it it needs to go and find it and then move it onto the l1 cache which is gonna push something else out of cache and then it needs to go find the next thing was there's not usually sequentially located so it's gotta go find it or it is and each object might contain references to other memory addresses which may contain references to other memory addresses so on and so forth so it's a very slow tedious process to get all of the data you need at once onto the CPU to be processed and then it's all gonna get pushed off by some other data and then you've got to go find it again and the process is very very slow so one of things we're talking about with with ECS with the entity component system is structuring our data so it's much more organized much more contiguous in memory so that we can not only grab a single record but then we can prefetch the next ones because we know we're going to need the next ones and we're not just going to end up prefetch and garbage and things like that so talking about streamlining the way we think about our data and the way we load our data so that when we want to process our data it can just be processed in serial now with ECS we don't actually restructure memory so it lines up like this we have these chunks and but this is kind of like I said highly simplified version of performance we're gonna move quickly right so that was time to run we we perform and that's kind of what UCS does and then we build on top of that we talked about the job system and what the job system does is it allows us to break up our logic into these jobs which can then be run parallel to each other so we can utilize all of our cores right which is it's also really cool for anyone who's ever written basically multi-threaded code it can be very very frustrating and just annoying when sometimes it even adds up being slower and you don't know why and you've got deadlocks and race conditions and all these things and our job system does a very good job of just letting you focus on the logic and letting us focus on the threads and things like that's very finally we have like the super awesome whipped cream cherry on top with the burst compiler which just automatically gives us tons and tons of performance there's tons of videos online about it and stuff like dad we're gonna see some of that performance just really really cool ways of taking advantage of your particular hardware to just have some really really awesome performance which can you know be actualized in a few different ways we'll talk about now one thing we don't talk about too much but I definitely feel that we need to talk about is when to integrate dots and urine projects you know we talk a lot about dots as the future and it's it's awesome and it does this and it does this but we really do need to address that dots you know doesn't cover everything yet so what are we talking about when should when do I recommend implementing dots well if you have a specific problem right if you have a game right now that runs completely fine with no problems whatsoever and you want to convert it to dots maybe wait right maybe it's not worth it just yet now if you have a specific problem if you are facing a real technical hurdle then it's very likely the dots can be a great solution for you to bypass that hurdle right but it's not something you just want to just start adding in everywhere unless you need it and the reason for that is that dots doesn't currently support all things right like dots animation is is not really released we saw an example of that with the dot shooter during the keynote it will be coming soon and there are a lot of things just that don't work with dots yet you know so we have a roadmap we're building these things but it's important to understand those current limitations if you have a technical problem that involves animation well then maybe you know dots isn't a solution just yet right so and you also probably don't want to just wipe out your current work and and just try to convert it all the dots immediately you probably wanna do this incrementally and that's how we're gonna approach it in today's talk we're gonna incrementally add some stuff and we're going to see how that what that workflow looks like some of the considerations we need to make that's very important so basically you have to think logically and make sure data is the center of your decisions now this is my one super cheesy joke I get one I stand by my decision to use it right here I always liked it I specifically added this because I was delivering a talk about this in China and I knew that joke would make no sense to them and that made me giggle so I decided to throw that slide in there all right so let's talk about how so we're gonna look at some code samples here in the slides then we're gonna get into a project and actually write some code and stuff like that but how do we integrate dots into a project well first step is to change the way we think about our data and our processes and I know that sounds really generic and very zen-like and whatever no free your mind and the rest will follow I believe it was Albert Einstein and said that but we are going to kind of start this process so let's say I've got three amount of behaviors representing three prefabs we have a player's script we have an enemies script and a projectile or bullets script here and I know that I want to convert these three things to to use ECS entity component system so I'm gonna start looking at this and thinking well how do i group my data alright because it's data oriented development rate data oriented design or whatever other acronym you want so how do i group my data so I can see here that player needs different things that enemy needs and enemy needs different things and projectile needs right and we can very easily just look at this and say okay that's that's not that bad that's not that difficult right we just group the data based on the type it is or how we want it to be accessed or what we want it to represent does that make sense right I see a lot of people nodding their heads and that's the problem this is completely wrong and this is fundamentally where we start going oh wait a minute what I thought that made sense because we're still thinking about these as individual things but thinking about a player we're thinking about a bullet we're thinking about an enemy those aren't real they never were actually no but those aren't real it's all just data so let's think about it as data we don't necessarily want to have redundancies right why when I'm processing my player if I am trying to move my player forward do I need to know what the players health is I don't care what the players health is while I'm moving it forward I don't care if the camera or the player is dead while I have a camera or any of these other things I want to focus on granular data getting my data down to small chunks that I can process just the day I need for anyone process any one chunk of logic so really we might structure it like this now of course I've opened it a few and I also have rigidbody on there even though there's not really a desk equivalent rigidbody it's merely an example but so I might say let's create a speed component and then all three of these things have that component let's create a health component that all three things have let's create some physics component that all three things have right so they can share that that doesn't have to be unique right we're thinking about the data atomically let's look at functionality functionalities a little bit different we're gonna write some systems and we need to think about the processes what do these systems do and so here I have an enemy update function and I have a projectile update function and we can see the projectile just move straight forward and no matter what flies forward doesn't turn isn't do anything the enemy is different though the enemy requires a bit of logic because the enemy is going to chase the player right so it's very easy to see that unlike the data right where things were very similar with our logic we do have separate systems here we could see that one system is gonna move our bullets forward and we have another system that is going to navigate towards a player so that the enemy can attack the player right makes sense right how we organized it like that again a lot of people are nodding again a lot of you are wrong all right this is exactly the problem again because we are duplicating our work what we see here is that we see a bullet moves forward but an enemy also just moves forward after it has been turned so we do have two systems here the two systems is one system to turn something or aim something and another system to move it forward because if you're a bullet or an enemy or a player or a train or an airplane or a beetle or whatever you move forward the exact same way you take your position and then you add to it some velocity times time in the forward vector boom you've moved forward that math never ever changes so just apply that to everything stop thinking about enemies in bullets in players and start thinking this thing moves forward this thing turns what does it turn towards I don't care give it some target and make it turn towards it right enemies can turn may be bullets turn if you have homing missiles or whatever right our systems do some atomic math functions right some in atomic logic our data is granular so we're only processing the things we need at any given time hopefully that makes sense let's look at one last example then we'll get into this project so we have these collision methods right so here we have when an enemy collide so if a bullet collides with an enemy what do we do and then a player collision so if an enemy class of the player what do we do now I'm not going to try a trick on this one we can see that obviously there's some overlap here we are going to have two systems right and our two systems are not going to be an enemy collision system in a player collision system our two systems are going to be a collision system oh you collided with something what did you collide with I don't know what did I collide with is it something I don't want to collide with if so reduce my health all right if I have a health assuming and then another system says oh or are you dead find me everything that's dead and let's clean it up right so one thing detects collision and resolve that collision another thing cleans up things that are dead right so again we're just looking at how we can break down our functionality in order to process our data view most efficiently all right it takes a little time to to make that that click I promise you it will and when it does then it's just like wow okay that makes total sense actually in a weird sort of way cool so let's look at a real project so I'm waiting for my mouse to come back there it is real project so here I have a project using all game objects and mono behaviors so may it play I want to run around I'm gonna shoot I can see my bullets are game objects over there in the hierarchy and if this was my game right now I'd have no reason to implement dots right because it's fine no technical hurdles everything that's working great animation I got no real problems so let's introduce a technical hurdle let's say I'm I'm instructed that we would like to have a spread shot like a shotgun for this character and let's also pretend that other methodologies like object pooling and particles and thing don't exist so I literally have to spawn a bunch of bullets let's just pretend it's an example so I'm gonna come over here to my players shooting script then I'm just gonna say alright let's use spread shot which is going to spawn a grid of 20 by 20 bullets ten times a second 400 bullets cool and I'm gonna hit play and now all of a sudden what I'm going to notice is I have introduced a real technical hurdle okay well that's not great fantastic so I have a real technical hurdle so what I'm gonna do is I'm gonna approach dots as a means of correcting that because again I for whatever reason I have to spawn these things I have to maintain these things as actual individual things use whatever mental logic makes that make sense in your mind but we're gonna pretend here all right so I've got to do this so the first thing I want to do is how do I turn my bullets into an entity all right now this used to be fairly complex and you had to create a bunch of different things and it was all this code to do it it actually has gotten very very simple in dots before I would do that actually I would come up here to my window and go to package manager and just grab entities and install it which is already in there so I'm just gonna go ahead and say cool I got that and then I have a script on my bullet so if I go to my prefab where my bullets live right here bullet I can see that my bullet prefab is a game object has a monobehaviour on here that makes it move forward fifty units per second has a lifetime so it both lived for one second before they get cleaned up it has a capsule Collider rigidbody there's nothing dot specific on here just a mana behavior and so what I'm gonna do is I just gonna go ahead and open that monobehaviour and I'm gonna see here here's my projectile behavior script and the first thing I'm gonna do here is I'm going to increase the font size so you can all see it better there we go the second thing I'm going to do here is I'm going to make this implement the I convert game object to entity interface well that's a nice one there and I'm gonna let Visual Studio auto implement that interface for me and what that does is adds this method here called convert and now I'm gonna be able to say okay it's gonna give me some entity that's going to represent this bullet when I convert it some entity manager some conversion system and it's gonna say hey you didn't implement this I'm gonna get rid of that now I've already created a bunch of data components right so I have say this move forward component which is actually empty there's no data in it it basically just says anything that should move forward will put in there I have a health component right which just has some value these things are really simple to write just I mean you don't even need serializable anymore but just public struct it's I component data and then whatever data is in it right to purely date and data I've got a few of these already written so I'm gonna add some so I'm just going to say manager dot add component all right like this I'm going to add it to this entity that will represent my bullet and I'm gonna say add a component that is the type of a move forward component just like that now in my convert method all I need to do is specifically tell it how to convert the things that are unique to my game transforms and mesh renderers and all that stuff gets converted for me I don't have to deal with graphics and rendering unless I want to but I am specifying the stuff that's unique to my game my bullets move forward that's the thing I wrote so I'm telling them I want to use it now I also need to specify how fast so I'm gonna create a variable type movie speed another one of those data components or chil just call move speed just for the sake of argument there and we'll say equals new move speed here and inside here I'm gonna say the value of that move speed is going to equal the speed of my bullet just like so and I'm gonna say hey manager again I want you to add some component data at this time so add component data on to my entity and this time I'm gonna pass in my move speed so that's gonna add that component and give it some speed one last one is I want my bolt to clean itself up after a while here so I'm gonna create a new time to live which I'll call TTL equals new time to live there we go and inside here again I need to pass some value and that's going to equal the amato behavior variable lifetime which I have there in the inspector and I'm gonna again say hey manager need you again I'm gonna add some data to my entity this time it's going to be my time to live there we go so all the stuff that's built in unity is converted for me all the stuff that's unique to my game I've just specified that I need here fantastic now how do I use this well if I come back to unity I could go to my bullet prefab once it compiles there we go and I could click Add component and add to this a convert to entity component here which is gonna automatically convert it for me but I don't want to do that because what that's gonna do is that's gonna convert this one bullet right when it's first initialized I don't want to create just one bullet right at the beginning of my game I want to create many bullets so I'm gonna do this manually I'm gonna do this through my player shooting script so my player has a script on here called player shooting and in here is where we're going to implement this use ECS button and and create or utilize these prefabs so I'm gonna come up here so I have this boolean use ECS I've also declared in here as some variables an entity manager and some entity that's gonna represent this bullet prefab and during start if I've said yes I'd like to use these yes I'm going to convert my game object bullet into an entity bullet so I'm gonna first say hey manager so we need to find the manager and that's gonna be found by saying world active dot entity manager there we go just like that and then I'm gonna say my bullet entity prefab is going to equal and then I'm going to call this long named method which is going to be game object conversion utility there we go dot convert game object hierarchy and it's going to say well what game object you want to convert well I want to convert my bullet prefab my regular bullet prefab and it's gonna say what world do you want to spawn this into and I'm just gonna say a world that active you can get into other worlds and things like that that's a little bit beyond today but there's some cool stuff you can do with that and so what this is gonna do is during start it's going to go ahead and turn that game object into an entity for me that I now have a template of and can use a bunch now I'm gonna come down here to my methods spawn bullet ECS which is currently blank and I'm going to add the code to spawn a bullet and so I'm gonna say entity bullets equals manager hey manager instantiate something for me instantiate a bullet entity prefab for me okay and so it's going to go ahead and do that and give that back to me now the entity itself doesn't contain anything the entity is just a way for us to find data out there right so I need to add some data that's associated with this entity so I have to do that through the entity manager so I'm gonna say hey entity manager I'd like for you to set some component data for me all right and I'm gonna set it on the end or the bullet I just created so thank you and now what am I going to set well I'm gonna give this a new translation translation is just our way of saying position now all right translation position same thing all right here we're just calling it translation all right and so it's value is going to be equal to and I have this game object called gun barrel and I'm gonna set it equal to the position of the gun barrel so bullet comes out of the right spot and then I'm gonna say hey manager I want you to set some component data for me again all right and again on the bullet and I'm gonna say new rotation that one didn't change its name and this one is going to be value equals and I'm gonna say quaternion we all love quaternion dot Euler there we go and I'm gonna pass in the rotation that's given to me in this method which is gonna be the rotation of the gun barrel right here fantastic if you're thinking oh man that's so much code to do I do want to point out that spawning a regular bullet is still game object bullet instantiate bullets transform position rotation it's really just a slightly different way of doing pretty much the exact same wet thing right just slightly different naming so let's go ahead back to unity here I'm gonna go ahead and let that compile then I'm going to check that I would like to use UCS I haven't implemented the spread shot yet so I'm gonna turn that off I just want to see if I can get entities so I'm gonna hit play and I can now you'll notice they don't appear here because right now for now the hierarchy doesn't show entities someday eventually we'll get those tools in place but I do have an entity debugger which allows me to say like show me all entities and I can see my bullets there and then I had that time to live I put it on it does clean them up for me so there we go cool so I'm spawning some entities it's really not a big deal the cool thing is this too because I like to work incrementally go back and forth if I do this now I'm back to game objects now I'm back to entities now I'm back to game objects to entities it's very non-committal we either run that conversion or we don't boom boom very cool all right so let's go ahead and create this spread shot to see if we've bypassed our technical hurdles spoiler alert we do so what I'm gonna do here is I could say you know do that manager down instantiate a whole bunch of times however there's a shorthand way of doing this to do it all at once I'm gonna create a native array native rays are this really cool thing they're awesome performant read save files really neat stuff so I'm gonna create a native array of type entity all right which I will just call bullets plural and I'm gonna say equals new native array there we go and inside here I'm just gonna say alright how many are in this array this total amount and I'm gonna say allocator and I can do all sorts of alligators I could do invalid that would be a really bad idea but I felt like it sure why not none I don't wanna do that either someone's a temporary job cool so it's gonna be a temporary allocator just because I'm doing something right now I'm not gonna need it for long periods of time and then I'm gonna say hey manager died instantiate but this time I'm going to go ahead and instantiate this bullet entity prefab and I'm gonna pass in my bullets native array so it's going to know how many bullets entities to create and it's going to store their IDs in this native array now Nate arrays are awesome they're fast really the cool however since native arrays are thread safe they can be used across multiple threads they don't know when they're done being used so I have to tell them when to clean them up so I'm gonna come down here after this and I'm just gonna say bullets not disposed that way I don't have any memory leaks or anything like that so I'm just gonna clean up after myself and then down here I'm just gonna cheat and paste the code where I set the component data for translation rotation this time I'm just gonna say bullets sub-index like so and then for my rotation it's also going to be bullets sub-index because I'm looping through all those bullets now and now I have this temporary rotation here temperate which is going to be this grid of X&Y to generate all those bullets now so cool so again kind of same thing it looks a lot like the monobehaviour version of instantiate and give it position rotation and then here we're gonna instantiate and give a position rotation again not that different so in here like I had said let's see if we bypass or technical hurdle I'm pretty sure we do let's go ahead and play all right so okay technical hurdle bypassed a lot of people do yeah check this out so that's nothing alright so that's that's 400 of bullets 10 times a second let's do four hundred bullets a hundred times a second let's do you know 900 bullets a hundred times a second okay let's do 1600 bullets 100 times a second all right let's go 2500 bullets a hundred times again all right you can just watch the entity debugger going why are you doing this to me 60,000 bullets this game is easy alright so right I mean just this is stupid right it's ridiculous so converting the entity or the bullets to entities does not take a lot of different process right it you know it's just a change of syntax and have to do these crazy difficult things and it's very non-committal like I said if I really want to go back to using game objects and experience the same technical hurdle all I need to do is turn off that that checkbox and I'm back to using game objects and going all this sucks why'd I do that cool now the next thing I want to look at is how do we approach writing system so that was the data alright we looked at how we structure some of that data and we looked at how we can convert something very easily that conversion workflow is awesome because it means I can work in game objects I can work with all the stuff I'm familiar with it's just at runtime turn it into entities and fantastic but I want to focus on now the logic so I'm gonna go ahead and turn on my enemy spawner now I've done the same thing with my enemies spawn err where I can use game objects or I can use ECS I just haven't already checked UCCS and I'm going to turn it on but it's kind of the same process where it has either an enemy is a game object or any an entity and I can just choose which one I wanted to spawn so it's gonna spawn some enemies here I'll hit play and where my enemies find me an enemy there's one so the enemies are there and I can shoot them pay attention to me but I really want these enemies to chase me right that's kind of part of the game so as much fun as this is I would much rather have some form of challenge if you can even call it that to my game so I'm gonna write a system which I'm gonna call turn towards player system now I do want to point out that I'm almost breaking my own rules here because I called the system turned towards player system however it doesn't have to be turned towards player players into thing you know there's no such thing as player it's all just data I really should called it turn towards something system turn towards whatever you want system turned towards who cares system but I have it as turn towards player system just so it's you know so the name makes sense so right now which is a public class and I have some code that I just don't feel like typing commented out here which I will uncomment here shortly but what I'm gonna do is I'm gonna create a new system that's going to make the enemies turn towards me so the first thing I'm gonna do here is I want to control the timing right I want my enemies to turn and then move I don't want them to move and in turn so at the very top of my system here I'm gonna say update before and then I'm gonna say type of there we go and this is gonna be the move forward system so I'm just gonna say hey this is some updates before that system so these things work in the correct order fantastic now I turn towards player system is going to inherit from job component system you can also do component systems but by doing job component system they're all spread out using the job system cross multiple worker threads if I just did a component system that run on the main thread and could potentially be a blocker so we would want to use job component systems as often as we can and now visual studios gonna freak out so I'm gonna let it implement the abstract class for me so a job component system has to have a protected override job handle on update which reads in some input dependencies and returns back some input dependencies which I don't have yet but I'll get there in a moment now besides that since it's a job system I need to create a the thing that is going to do and these systems have a couple parts the first part is some query which specifies what data you're operating on and then some execution what do you do to that data and we're not saying find me all the enemies find me all this find me all that we're just gonna specify data that we want so I'm going to say it struct no not stack trace utility struct trying to help I appreciate it then I'm just gonna call this man turn job whatever and I have a lot of different things like do I could do like an eye job I can do an eye job chunk I can do a job you know for each with entities and I could do a job parallel fours and whatever I'm gonna do an eye job for each right and I'm gonna specify my query right here it's a nice shorthand way I could create entity queries and do all these really complex things this is a nice shorthand way of saying hey I want a job and this is what I want you to operate on all right so I job for each and I'm gonna say a translation if I mean everything that has translation and rotation thank you very much that is what I'd like so we're this is our query and it's gonna say hey you need to implement that so again code complete to the rescue so I'm gonna rename this to my position and this one to say rot for rotation there we go so it's gonna say alright so fine for me everything with a translation and a rotation and in my execute method for each entity that matches that query I'm gonna get its position and its rotation and I can do something to it so saying give me this data I'm gonna chop it up do something to it I'm gonna put it back now give me the next set chop it up do something put it back right so inside here I'm gonna go ahead and write the code that's going to allow us to turn towards our player now where is the player I don't know we're only asking for translation and rotations of the entities what about the player the entities don't know that I'm about to tell them that so I'm also gonna provide to my job some outside help so I'm gonna create a public float three player position and I'm gonna pass that into my job I do a slightly different way so here inside execute is this code here that I didn't want to type out so I'm just gonna cut cut cut that paste it and then uncommented a.m. there we go so this is standard rotation code basically we create a heading by taking one position minus another one I don't want them to go down or up so I'm zeroing out the Y so they only move horizontal and then I'm using a quaternion look rotation to make it turn towards that vector and that's the rotation so this has nothing to do with dots it's just rotational stuff so that's why I didn't want to type it all up and so that's this job this job is very simple find me all the entities of translation rotation give me a position I will make them turn towards that position fantastic doesn't have to be the player so I really should rename that but but whatever alright so inside my method here on update the first thing I want to do is I'm going to say by the way I have this singleton some of your creme you don't ya a single things I have a singleton here that's just going to help me out so his player dead because if the player is dead then I'm gonna return because yeah I think I need to return input dependencies because I need to return that type so if the players dead then we're not going to do anything special there we're just gonna leave and that is a method otherwise so the players alive congratulations so I'm gonna create so a variable so I'm job is gonna be equal to this is gonna be my new turn job I hate using var I don't know why I did that but there we go especially in sample code but so we go turn job and I need to specify what this term jobs player position is and again settings to the rescue player position here so there we go so I'm just saying alright let's create a new job I'll so I I'm team new line I don't like it when people put curly braces on the same line that's me so job in the player position is this so that's how we're getting that information up here finally so I've created a job I've given it the data it needs I need a schedule it job get to work job dot schedule and I'm gonna say yeah you're doing this you're doing this now and here are your input dependencies so that's what was read in to this method right up here that's how we structure our ordering so we can say okay well you need to wait and do this or these are the things you have to wait to be done before you run in so on and so forth and we need to return back a job handle so can return back the result of this scheduling so that the next thing can use them is dependencies and whatever and we can set up their structure here so there we go we've created a job alright so we've defined the actual work to be done which needs each entity's translation rotation also needs some position on execution we turn or change the rotation and then we don't even like turn something towards something else I should stop saying that we don't we change the rotation what that does I don't care stop thinking about individual things and then on update we're gonna make sure the player is not dead they're not dead we're going to create this job and schedule it cool so no there we go so let's see here what that does so I'm gonna let that compile I don't need to tell the system to run the system is gonna have a query if something matches that query it just runs all right so I'm gonna go ahead and hit play and now my enemies are chasing me fantastic that's great now here's a problem that people often have when they start doing this right it's a bit of a gotcha moment when they go perfect my game is working I'll wait a minute I did say anything that has translation and rotation didn't I well bullets have translation rotation as well now this isn't really a problem I'm gonna call this a feature because now I'm a spinning wall of death and no one can harm me by the way if you suffer from photosensitive seizures look away I thought I should have said that a moment ago but there we go so not a bug a feature and I'm awesome but let's fix this okay so again we often do this where we write our queries and we think good this will get me all the enemies and it will get you all the enemies but it'll get you anything that matches that query because there's no such thing as an enemy there's no such thing as a bullet there's no such thing as a player so what can I do here well first off I have this thing and again I'm breaking my own rules I created a thing called enemy tag I had to say this thing is an enemy I shouldn't do that I should say this thing turns towards something tag or whatever right to specify that it's something that needs to be turned by this system turned towards tag or whatever I also call it tag specific because there's no data inside that's just something I do that's not a standard or anything like that because enemy I might think maybe there's day in there but this is meant specifically to identify the enemies my game it is empty it's not even empty data it's no data but it's just something I can put on it that I can use as part of this query now in my turn towards player system I could add it to my query right here enemy attack however it would query for and attempt to retrieve that data and while that wouldn't result in an error it's also not the most efficient because there is no data there I don't need you to go get the data I just need to make sure it's there I just need to make sure this has the enemy attack so I'm gonna use an attribute instead on my job and my attribute is going to be called require component tag all right and then require component tag type of there we go and enemy tag there we go so it's saying I don't need the enemy tag just make sure that everything that I query for has it all right and that's just some means of filtering also while I'm here I'm gonna enable burst compilation burst compilation is awesome it's magical it's cool and it's really really really easy to use here's I'm gonna do it done alright first compile it is now going to work with burst compilation fantastic most people always say well if it's so awesome and so great when why would you never or why would you ever not use it exactly you would pretty much always want to use it the only times you don't want to use burst compile is one if you're debugging and you get a message in the console that says hey the thing you're trying to debug turn off burst compile so you can see it so we can actually stack trace it or whatever cool and turn it off and debug in and turn it back on or if you're doing stuff like with strings or anything that are that are not safe for burst you'll get a message and it'll say hey by the way you said you went in bursts but we couldn't do it on this particular job because of this cool all right that happens right but otherwise I have this on every single one of my jobs and it's awesome cool so let's come back here and let's see does this work I'm sure you can guess so enemies chase me and I blast them into bits fantastic now one thing that's often misrepresented when we do these demos because you know I like building these demos we always love showing just tons of stuff and it's flash it's cool so everyone always starts to think well you only use dots if you need 20,000 something a hundred thousand or something doing these things and it has to be big and flashing you need 20 billion enemies and whatever right that's not the case we do demos like this because they're super fun to look at right if I did a demo and say hey look I'm generating less mobile battery heat you'd be like okay right you wouldn't care right but the fact the matter is is performance is performance I take that performance and I crank it up and have a bunch of extra bullets and stuff like that but let's say I was still only firing one bullet and I had just one enemy chasing me or whatever I would still do this it still is a good solution because that performance even if you don't use it means you're running less CPU you're using less memory you're generating less heat on mobile devices that means no more battery drain or much less battery train not no more battery drain that would be amazing right never uses battery again no less battery drain things like that you don't have to push this to extremes you can actually just enjoy the performance yeah right it's proven that the apps on App Store's and stuff like that you know one of the biggest things that takes them from a 5 star to a 1 star is my phone really heated up or just ran really poorly or just killed my battery I'm uninstalling it things like that so don't I mean enjoy performance for the sake of performance you don't have to just crank this up to insane amounts that being said let's crank this up to insane amounts so right now I am spawning one enemy for every one second those are rookie numbers we gotta increase those so let's do 100 enemies I don't know 3 times a second sure all right let's you know what let's be reasonable let's go a hundred times a second 900 bullets that seems reasonable all right and I'm also going to turn on my profiler here so we can see kind of what's happening ok I also want to point out I'm gonna in a moment give you the link to this project on github you can check it out the collision system in this is awful it's probably the worst piece of code I've ever written it is a terrible collision system I wrote it this way intentionally to show you that basically what's happening is every enemy is gonna check for collision against every single bullet even if they're nowhere near each other and then the players gonna check for collision against every single enemy every single frame on the main thread it's beautiful how awful this is don't write your code like that but I wanted to show you the performance we're gonna get out of this all right just even though it's it's so so so awful all right so I'm just gonna stand here for a little bit just get get some enemies coming okay and so where did we end up with this so we ended up I mean that's a little less than hundred it's not quite 60 so still above 60 frames a second I don't know how many I really should put a readout to show me how many enemies that was and how many bullets that was why my entity bugger so I can see how many you saw 432 enemies right now all right getting closer so we've got right around here so we're gonna have 1600 enemies and so okay 2100 enemies I know my fire nine hundred bullets a hundred times a second so that's going to spike me close to fifty thousand before they clean up so that's gonna be two thousand one hundred thirty-two enemies checking for collision against each of them checking for collision against fifty thousand plus different bullets all at the same time so if I can pull this off because I'm gonna hit pull I'm gonna leave pause man I'm gonna die really close to me so okay there we go BAM so not a problem at all just whatever you're luckily I've muted the audio because it sounds like a disaster with temping enemies dying all at once but there we go and we even have the enemies that die spawn little particle effects I don't know if you can see that whatever and that's all done on the main thread so yeah so just ridiculous fun right just just spiral my game is awesome okay so that's right really really cool there's a lot we can do with this the most difficult thing is just sort of wrapping your head around the different way of thinking about things it's not intuitive because humans don't think about stuff like that we look at something goes that's a car we don't look at that and go that's the color red number of wheels for doors for maybe we don't look at it like that we don't think like that right even in schools we all learn object or any programming we don't really learn data or into programming so the best way to think about this is to think about dots as if it's a database and you're just running queries against the database find me this data do some of the data put it back think about dots as if it was a shader for your CPU right the reasons you would do things on CPU versus a shader on your GPU same reasons of minor behaviors versus dots right these kind of the same concepts where we're streamlining and thinking about data just like we will be the shader all right so we are just about that time here I'm gonna go ahead and put this up this is a link you can grab this project from github I'm constantly updating this with the latest stuff I believe there's one new release I can need to update to but I will be so feel free to grab this project check it out don't message me and tell me the collision systems awful I know I'll find you I will find you it's it's generally like that check it out see what you can do with it play around with it have a lot of fun if you have any questions reach out to me my name is my guide Mike at unity3d comm or at Mike GOG on Twitter I'll be around here I've got a minute 13 seconds left I'll be around here for some questions even on stage but off to the side but otherwise I want to thank you all for spending some time with me hopefully the rest of you night is awesome and have a great show Cheers [Applause] you [Music]
Info
Channel: Unity
Views: 55,299
Rating: undefined out of 5
Keywords: Unity3d, Unity, Unity Technologies, Games, Game Development, Game Dev, Game Engine, DOTS
Id: BNMrevfB6Q0
Channel Id: undefined
Length: 43min 59sec (2639 seconds)
Published: Thu Sep 26 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.