How Unity3D Addressables make assetbundles easy and your project faster

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

I love your room

👍︎︎ 1 👤︎︎ u/jKinsley1 📅︎︎ Oct 10 2019 🗫︎ replies
Captions
hey what's up I'm Jason and today we're gonna talk about saving memory in your unity game we'll talk about what happens when you reference and load assets currently and then we'll talk about the asset bundle system and more importantly the new addressable system that's built on top of it in fact that's gonna be the main focus of this video we'll talk about some of the cool benefits that you get from it like faster build times and smaller downloads of course along with faster iteration which is probably my favorite which just means hitting the play button and having a start as fast as possible but you also get a benefit of faster load times and just seen loading and seeing transitions so if you're interested in this kind of thing the best thing that you can do and the thing that will make me happiest is just share it share it somewhere I don't care where anywhere that you share it the YouTube knows about really helps more than anything if you're not that interested then like and subscribe and all those things too and if you have questions about this stuff please drop a comment also if you go through the video and you have other suggestions or recommendations for more stuff that I didn't talk about in here please just drop comments down below and let me know and maybe I'll do some more updates and stuff alright so I've got a scene set up here where I pulled in the free cartoon effects I still love that pack it's just awesome little particle system that's free to use and I've got a particle spawner object here that I can click on and you'll see it's got references to four things these particle references and they might look a little bit weird right now because they have dropdowns don't worry though we're gonna dive into that in just a moment so let's hit play there we go and let's watch what happens when I click my three little buttons or four little buttons at three zero three three four buttons right so we click on them and we get some particles appearing that one actually spawns a whole bunch of particles that one spawns one that one spawns one and that one spawns one nothing special right who cares we're spawning particles but let's look at the profiler so if you haven't opened the profiler before it's just under window and then analysis and profiler and here I've got my profiler scaled down and just showing the memory part but if I pull this up you see it's just the normal profiler same thing that you have to scroll to the memory part and then I drag it down like this so it see it a little bit easier so what we want to look at here in the profiler though isn't this little chart I really don't care too much about that just because I can't see the numbers on there and right down here I can read them perfectly and I want to look at this texture memory look it says that where we have 116 0.5 megabytes of texture memory in there now if I click on 0 watch what happens see it went up to a 17 point 7 and then look at that it went right back down to sixteen point five or one sixteen point five and if I click on all of these watch I kind of click on them all at the same time you can watch those numbers go up and then drop back down now you might think like ok whatever it dropped back down a couple of megabytes who cares it's because the thing got destroyed it's actually not because the thing got destroyed at all because if we do this in another scenario in fact let's go do it now let's go open it up without the addressable x' and see what happens so we'll go into our scenes go to our basic one and hit play this is very similar example I'm gonna select the spawner though and let's take a look at it this might look a little bit more familiar these elements with the little search box right that's how we normally reference things or how I at least used to normally reference things before I switch to using addressable as for as much as possible so here we go we've got our spawner set up and I'm gonna go to the profiler one more time and it's important that I do this right at the beginning because you know so well you'll see why look we're at one 16.5 let's at zero we're at one 18 and did you notice that it didn't go back down when that got destroyed and didn't go back down didn't go back down I'm clicking on all of them I mean the the memory usage of course goes back down but the texture part isn't going back down so we are destroying the objects we're still freeing up some of the memory but we're not unloading those references to those textures that were no longer using now we might not want to necessarily unload them all either it's possible that we have a scenario where we don't want to unload them ever and there's a way to do that we'll talk a bit about that but in my case I've got some games where we've got a lot of assets we've got a lot of memory pressure and if we're done with something we're not you anymore we want to unload it we want to pull that out a memory now if it's something that we're just gonna respawn and keep popping up over and over of course we'll just pull it we won't unload it we won't we won't need exactly this thing to fix it right we'll fix it a different way but for the cases where we're not doing that where we actually watch free up the memory we're not going to use it again until we need it again this is a perfect solution now watch this I'm gonna stop playing we're gonna play one more time and look at the memory because this is the the best part still add 121 watch I click these and no change now if you're new to unity this probably comes as a bit of a surprise what's actually happening is all of these things were actually loaded in beforehand or they're loaded in with the build when the scene loads it's just the editors kind of not really pulling them in until I hit the button the first time but if I did a build they're gonna be in there the first time always just because they're referenced in fact I like this I today I learned prefab references and inspector are loaded into memory even if not instantiated there are a lot of posts like this a lot of time people discover this it's like a new revelation that oh I didn't realize just because I'm referencing these things unity assumes that I'm going to need them it loads them in and it has now if you use asset bundles before you probably know this stuff and you're like okay this is dumb I know obviously we have to manage our bundles we have to manage our assets or else we're gonna have all these things in memory if you used to ask that bundles then hey this is gonna be good for you too because we're gonna dive into well this is kind of the replacement for asset bundles it's actually a system built on top of it and that's the addressable system and I think it's time for us to dive into how to actually do it so let's do that all right to demonstrate this we're kicking off a brand new project I want to make sure that I don't skip over anything and that you don't miss anything so I've got my project view here and I'm just gonna go find that cartoon effects pack again so just go to the project view type in cartoon effects and on the asset store tab here I can see it it's right there I just right click hit show an asset store and import the entire thing they're going the demo scene just to make sure that everything looks cool and fancy like it always does so we've got our cartoon effects in the next thing we need to do is well I want to go back to my sample scene and then I'm gonna open up our package manager so we go to window and package manager and we want to find the address of bowls package so just type in ABB and it should find it and then we'll install it once that package is done we should be able to go to window and then go down to asset management we should see an addressable option click on that and you'll get a new window that lets us create addressable settings or import them we're just going to create new settings so click on that button and we get the new addressable window and we also have a settings object if I click on this profile and hit inspect profile settings you'll see it actually selects it down there in the project view this asset is my settings for the addressable z' and then I have an inspector over here where I can actually modify the settings for the addressable --zz we're not gonna dive into that just yet instead what we're gonna do is go find the objects that we want to make addressable the objects that we want to be able to spawn and be spawn and load and unload from memory so to do that I'll just go into my normal project view and I'm going to take my addressable window and I'll just dock it right up here for now and I'll get rid of the package manager because we're not gonna need that for awhile in fact I don't think we're gonna need that at all so let's go into cartoon effects and just find a cool particle effect so here's smoke + text and look over in the inspector you see here where we have the name and then we have the tag and the lair section look underneath there's that addressable see that right there click on that and then we suddenly get a text field where we can set a path for it and if I expand out this default local group you'll see that the address has appeared here so the address is here or the address to the actual object the path is showing right here very long - and there's a little button that I can click on in a label thing first I'm gonna shorten this path down because it's really just too long I don't need this entire path or this entire thing as my address so let's let me go re-select that accidentally hit the wrong hotkey so I can reselect it just by double clicking on that little icon by the way and then I'll go over here let's find the end of this just use ctrl in the arrow to kind of bounce around and I'm gonna grab just the end part hit home shifting home and then hit delete and I'm gonna call this a VFX slash CFX explosion so that way it's somewhat grouped but it's not this giant long path and I don't know that this is necessarily a great way to name them I just don't like having the very long paths and I don't want them to be too short so I've been putting the type of thing they are and then a slash and what they what the name is or what the address is so notice that that updated it in here too but the path part still goes to the prefab and I think I said those backwards earlier when I was saying it the address is on the left the path is here hopefully if you're watching you're like what are you talking about Jason it says the opposite right there so there we go we've got an address we've got a path here and that's set we don't have to do much else except for click on this build and hit build plate or content so we now have an addressable explosion that we can use we just have absolutely zero code to use it so let's pull in some code I don't want it to sit here and type it and waste your time so I'm gonna pull it all in we're gonna go really quick over what the code is and how it works all right let's start our dive into code with something simple you may have noticed an extra file here that I deleted by the way that was just extra crap that we didn't need so it's gone let's open up the particle spawner button first though because that script is relatively simple we'll open this up and here we are in writer I'm gonna scroll that over or slide that over just a little bit we've got a couple fields here we have an index and a spawn count this is just so I can control how many we spawn the index is for which particle system we want to spawn right now I'm trying to keep it simple and just do them by order in that that element array that you saw will dive into that in just a moment you see how it all works but we've got one method here that's public this request spawn particle might have kind weird name - and wondering why it has requesting we'll be diving into that - but what we do here on live 11 line 11 live line 11 is loop through our spawn count we find the particle spawner and we call spawn and we pass in our index now of course super inefficient don't do this for real don't loop through something and do a find object in the loop but this is a very simple example and this is not the important code this is the zero percent important stuff I just wanted to show it so that you know what it is and kind of understand how it works if you're trying to replicate this so we've also got an on validate method on validate just gets our index and it does that by getting the transform sibling index so when I put a bunch of buttons under a panel it goes hey button zero is or the first button is button zero index zero and then it sets the text to say zero one two three four or whatever and then in the update method we check to see if a key was pressed and if one of those was pressed we call that request particle or spawn particle now the other reason that this is public is because it's on a button and I just link it up in the scene now I'm gonna do that real quick and show you how that's done but we'll do it really fast so that we can dive into particle spawner stuff so just go in here we go game object create a UI and we'll make a button go to the scene view we'll find that button go to 2d mode zoom out real quick on this canvas I just add a grape component so it's a grid layout group so that it puts them all in order and we'll make them like 30 hi 100 wide that looks good select the button and we go down here and we'll add our component there's a search for the word button get our particle spawner button and you can see that the text already changed to say 0 on it and if i duplicate that button it would say 1 on the next one but i don't want to duplicate it yet because i want to add the on click so click on plus for the on click take the particle spawn or drop it into there select no function go down here pick particle spawner button and then request oh it's just barely on there you can see the re qu es right there in the corner but we want to pick the request to spawn particle so I've got that there now I want to just duplicate is button a couple times one two three there we go I've got four buttons and look at that this time I'm going horizontal I could change it and go vertical or something but let's just go across the horizon make it a little bit different this time there we go we've got our buttons set up and I'm gonna save my scene now let's talk about the actual code that we're here for the addressable stuff the particle spawner system and let's do that by just opening the script up first well if let's look at our using statements we've got a using statement for addressable assets and for resource management a sink operations it's important to note that if you are using the assembly definition sorry I've lost my boss my word there but if you're using assembly definitions you'll need to make sure that you reference these things in your assembly definitions to here we're not doing that because you're trying to keep it simple but something that you might come across if you're using those now we have in here a particle references that is serialized and it's a private list of asset references and this is very very different from normal usually you wouldn't see a list in the serialized thing and asset reference is not a type that anybody's used to it's also not some special type that I made or anything it's part of the asset bundle system asset reference is what we use to reference our objects so let's go put the particle spawner script on a game object and see what that looks like real quick so go over here we'll create an empty game object and I'll just call this particle spawner with some square brackets just makes it a little easier for me to find it and we'll add the particle spawner now if I expand out the particle references you see that just has a size of zero and nothing else and if I change the size to one it works a lot like a regular array would so it's just like you would expect but now we're using a list and it has a slightly different drop-down so normally when we do a game object reference we have that little circle and here remember I told you we'd get this little drop-down thing that kind of seems different might be wondering what it is we click on it though you can see that we can actually find all of our addressable as here I only have one thing here so I can just select it but if I have a big list of things I can type in there in search and filter when we add more things will do that will filter as he can see that in action or you can just go ahead and add a couple more things yourself if you want so there we go we've got our particle spawner setup and we've assigned one particle or one particle reference I guess is what I've named the thing let's dive back into the script now and see how it works so our spawn method here is the one that's getting called and don't worry about these two dictionaries of cues we're gonna talk about those in just a moment one of them is for more complex they're really both for unloading things we'll talk about them in a bit though but let's look at the spawn so we have our public void spawned and remember this is called from our particle spawner button I'm in writer so I can click the one usage and actually go right back to that bit of code I'll hit f12 to go back to the spawn so we pass in the index based on the button so 0 for the first one and you know all the way through we check here to see if the index is invalid just to make sure that it's not bad or that we're not putting in an index that's higher than our particle reference count or higher than or equal to because we don't want to have a ref since we're zero based we don't want to have a number greater than our count then we get the asset reference from that list by index nice and simple the next thing we do is check to see if the runtime key is valid if it's not valid and just log it and return I'm not a hundred percent sure that we need to do that but I think that we do because if the particle if the reference is just set to nothing or empty then we're gonna run into a problem now I might not need to do the log but I should probably definitely at least return out of there the next thing we do is check to see if this async operations handles contains key of asset reference and you like what is this and this is because my asset bundle system or the setup that I have is a little bit more complicated to be able to automatically unload all of this stuff for me so what we're doing here is let's go take a look at the dictionary we have a dictionary that has a key of asset reference so we'll have one entry in this dictionary for every different reference that we use and then we have an async operation handle with Ty game object so what this is doing well let's go back down to the code we're checking to see if it exists if it does exist then we are saying hey if this thing is done loading then spawn from the hour loaded reference if it exists here but it's not done loading then we in queue it so all of this is kind of like our after we've already loaded and spawned and we want to spawn more things code we'll talk about it in a moment but this isn't really how it works sort of the order that the things flowing so I'm gonna minimize this and what actually happens the first time we come through is load and spawn will get called because we're not going to contain that key yet so let's dive in to load and spawn load and spawn calls addressable as that load asset async and here's where we give it that asset reference so this is how we load the asset without just instantiating it and here we're literally not instantiate we're loading it into memory and getting that asset operation or that async operation handle and then we can use the asset reference to start spawning our object and let's take a look at how that works so we get the operation here remember this returns that async operation handle and then we add it to the dictionary with that asset reference as the key and then we add a callback on the uncompleted or the completed event for our operation or our are loading asset async and when this is completed this is the code that I'll call will spawn a particle from are loaded reference and then if we have any queued up spawn requests will spawn those as well now again I feel like this is kind of complicated but hopefully you're able to follow along and again up make the code available so you can just step through it if you need to so let's look at the next part so what happens we call spawn we load the asset or we tell it flowed but since it's asynchronous it's not going to finish right away we're gonna kick it off we're gonna put it into this dictionary and then we're gonna say hey whenever you complete run this little chunk of code in this little lambda statement and the first part that's gonna run is the spawn particle from loaded reference let's go to that because that's gonna look a lot easier here we say asset reference which is our new asset reference that we now know is loaded instantiate async and we give it a position and a rotation just like we always do here I'm giving it identity because I don't care about the rotation its particle and we're just giving it the position that we passed in from our other method in fact let's go back up one oh it's right here from get random position so get random position just giving us a random spot and that's what's getting passed into here so we call instantiate async and again notice that we're calling something on the completed so we're registering for that completed event and the code that calls when this thing is done instantiating is right here and this is a little bit different this is kind of where using addressable x' gets to be a little bit different than spawning regular game objects because we're still instantiating it in an asynchronous pattern we need to use this callback to do things when it's done we can there's kind of a way that you can hack it in and make it synchronous I wouldn't recommend it and I don't think that unity recommends it they have all those methods marked as obsolete and I think that they generally recommend going with the asynchronous ways into why so what happens here is we spawn the object the completed fires off and it runs this chunk of code like I said but here we're checking a couple things first we're seeing that if this spawn particle systems dictionary contains the offset reference this spawn particle systems is a dictionary that's a list of game objects in fact let's go look at it it's a dictionary of lists of game objects so we have an asset reference and then this list would be all of the spawned versions of that particle system that we have out in the world so it's by the key of the reference and then the instance is that list or the instances are in that list I mean so after we've instantiate it that list if it wasn't already instantiated we add the result here which is the actual game object to our list so that we're saying hey this is just a list of all the spawn particle systems that we have and the reason that I'm doing that is so that when we run out of spawned particles Thums we can unload this thing automatically and I don't have to go in there and we'll manage it some other way this is basically just my little easy way of managing this thing now I think in a real world scenario of course you're gonna want to be able to flag certain things as don't do this or perhaps put some timer on it so that if it's unloaded and none of them have been used for 30 seconds or maybe not in this scene or whatever then remove them but for now I think just clearing it all out right away is a great example and shows how easily we can do that so we've got our spawn particle system added to the list and then we add this notify on destroy component I like with what's this what is it I don't know well well dive into that in just a moment it was one of our three scripts that's our last one in fact let's dive into it now because it's tiny it's a little monobehaviour that has a destroyed event on it it has an asset reference and a non destroy so when this thing is getting destroyed when our particle system is dying we just call destroy dot invoke and pass in the asset reference that we have so what is that doing it's just telling us well here if we look at the destroyed call back it's calling into this remove which is releasing the instance so this is again I guess a very important part of how this all works but I don't know if it's very obvious or very clear when we spawn these objects with the addressable instantiate we need to release them with the addressable system as well so we can't just spawn it have it destroy itself and have it go away we actually need to release it with this addressable release instance now this notify on destroy is not obviously the simplest way to do it it's just that I'm using particles that have a on destroy timer already built into them with the cartoon effects so they already killed themselves after a certain amount of time I didn't want to add cooling and didn't want to over complicate this so just on destroy we're calling in and getting that call back to here so that's really all this is for don't think that you necessarily have to do it that way you just need to find some way that when your object goes away when you destroy it you call the release instance on it so we're calling release instance and then we go into our spawn particle systems list for that asset reference and just remove the object again remember that ondestroy gets called before the game objects null so we still have a reference the game object even though the destroy was gone in fact that's why I remember when you do the not equals null check or the question mark dot operator it'll tell you hey this could be invalid and if you hit the little button and write or it'll tell you exactly why that's because the objects not completely gone so we still have the object long enough in that ondestroy callback to be able to remove it from the list and release it and then here this is kind of where I do the rest of the little bit of magic we check to see if that list is empty if it is I just write out a little log saying hey we emptied out that list which is of course just generating some extra garbage for no reason but showing us what's happened and then if the asset reference is still valid we release it so we call that the release instance but the addressable is not release and we released the operation handle so this is why we're holding on to that handle we need to release that handle to remove the object from memory completely a whole lot there so let's dive into the project one more time and just see it in action but this time with the addressable memory profiler or the addressable profiler so go to window and then asset management and open the addressable profiler and then if I hit play and I click on some of my buttons here let's see you see that nothing really shows up but if I hit clear and click on them you see that we start to get a little bit of data but I'm not getting any data about this explosion I'm gonna stop playing and we need to go to the addressable window one more time go to the profile settings or just go select this object and go to them we need to check the send profile or events button now if I go back in and hit play and again I may need to hit the Clear button again I think it's just a beta issue but if I hit yep let's it clear I hit play you should see that my game object is actually showing up there and if I click fast enough you can see that I'm getting a whole bunch of memory usage from it and then it drops back down it's not a whole bunch it's just cuz it's small texture but if this were a big thing you could see I'm spawning all these instances of it at least and my memory usage is going up and then when they're all gone as soon as the last ones destroyed this thing disappears perfect right so that's the goal that we're kind of aiming for we want to be able to have these things load and unload maybe not always automatically like this but at least in a way that makes sense for our game and it's pretty easy to do and once you're on this addressable system not only can you do all of this but you're gonna get much faster startup times because all this stuff doesn't need to be loaded into memory right away at beginning at the beginning of your game you get better memory management in general and I think you became kind of set and ready for the new way for setting up systems and games in the future I think that the new ECS stuff are the new dots that it's coming out and becoming a big thing is gonna take addressable is kind of probably to the next level or at least used addressable a whole lot to make the system's work and I think that if you're building an assistant or any game that just has to get updates or has to get patches or don't you just want to have a nice easy to use system this is kind of it so if you're not using addressable yet I highly recommend you just experiment with it you know grab this sample project play around with it a little bit see what you can figure out and then see if you can find a good way to integrate it into your projects because it does have a big payoff I think it's really useful and it's something everybody should probably figure out eventually anyway if you like this kind of thing again the best thing you can do is by far just share it share it everywhere you can also yeah I wanted to say a special thanks to everybody on patreon I say it all the time but it is really are awesome and it's really cool that everybody really supports the channel and all the stuff we're doing and yeah if you're not into either of those things I like in a comment is great too anyway thanks again appreciate it if you have tips on addressable please share them I'd love to hear more and if you want to see more addressable as related content you know and I'll keep shooting more of these videos you
Info
Channel: Jason Weimann
Views: 99,183
Rating: undefined out of 5
Keywords: addressable assets, unity, unity3d, unity3d college, game programming patterns, unity3d solid, assetbundles unity, asset bundle browser, asset bundle, unity3d addressables, unity tutorial, unity game development, gamedev, assetbundle, game development, unity asset bundle, asset bundles, assetbundles, unity game dev, memory leak, addressable asset tutorial, unity3d addressable assets, unity 3d, game dev, asset, addressables, unity instantiate
Id: uNpBS0LPhaU
Channel Id: undefined
Length: 29min 7sec (1747 seconds)
Published: Mon Oct 07 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.