Unreal Engine 5 Tutorial - Open World Optimization: Don't use actors too much

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone uh this is a recreation of an old video about improving n FPS uh in a game and this time we're going to talk about instances so as you can see on the screen right now I have a huge forest and it gives me something around 100 FPS when I'm looking from the top and if I will move inside of it it has a lot of vegetation and it gives me 70 to to 9080 FPS also everything here is interactable so I can go and for example pick up some branches okay pick up something from an nurse and so on so first thing that uh we have to keep in mind is how we are creating forest in my case I'm generating a forest using a PCG so I have such PCG graph for a forest and that's it and uh here I'm spawning for example trees with different trees and so on so on so what is the main uh thing that we going to do we're going to replace every in instance with some actor and uh when we're close to it and we're going to replace every actor with an instance when we are far from it so let's start and we're going to make it very simple and adjustable so that uh every time we're going to add a new vegetation or we going we will CH change aesthetic mesh for a tree our component will still work or it will take a very small amount of time to change it so what I'm going to do I'm going to open my folder with components and create a new component and it's going to be forest for example [Music] optimator also what I'm going to do I'm going to disable my old component let me find it here it is so now we've generated a forest okay it's not a way to disable it let me just delete it so now we have everything here that is not interactable also PCG allows us not to spawn static meshes but to spawn in ectors and if you will spawn nectors instead of static meshes you will mention how a huge FPS drops because holding such big amount of actors on the scene is too hard it uh will not be able to render with a small render time that's why we are using an instances so don't use spawn ector here only if it is a very small amount of actors here on the PCG on the static mesh spawner you can also see a component class that is selected for static mesh so it is spawned in hierarchal instant static mesh component we have few selections here instant static mesh component here archal grass and Fage I don't remember what grass and foliage does foliage is used when we're painting foliage it's used for grass that's Tain on Earth and so on I think grass is the same as Fage but with some small changes the main two are instant St static mesh and karch if you don't have any lots for your static mesh like let me open a tree if you have only L LOD zero then you don't need to use garch instant static mesh karch instant static mesh allows to change loads for in for an instance so loads will work for every instance in the hierarchial static mesh now let's open our folders that we've created for a forest and let's create a new blueprint actor component and call call it for Forest optimizaton owner of this component and promote it to to variable call it ched okay uh next we're going to call some function called setup so let's create this function and call it setup and call it from begin play so what this function going to do it's going to add some uh overlap Collision to our character so let's get a character and add component by class class and select a box component it's a box Collision we have to provide a relative transform relative transform I think that we will um we will use let's open a character by the way BP main character and let's add the a box component here let's add a box Collision like this move it a little bit here and select a size for it but not using a scale let we should change an extent an extents so let's Place 90 here 90 here and 180 for example on Z axis and I think that it should be be longer on xaxis let's make it 200 here and 200 on Y and I think such box maybe even 300 on X such box is fine so every instance in this box will be replaced with uh every instance in this box will be replaced with some exor so let's copy location of this box and paste it okay we cannot paste it here well location is 200 on X and Y and Z stays zero now let's set an extend for this box let's call set extend without any updates of an overlap and extent is just a half of a size so we don't need to know this we will just copy this extent like 320 and and 20 uh 300 200 and 200 so X is going to be 300 200 200 100 compile and save and now we can delete these box from each character because it will be added by a component now what do we need to do we need to make this box to overlap with our forest but it should not be overlaped by other actors so let's open our settings project settings and create a new Collision for our box here on object channels we can create a new object Channel and let's call it for example Forest vegetation replacer and by default Forest vegetation replacer and by default it's going to it's going to be ignored by everyone I will not uh tap accept because I have already created it in my previous old video but you should Ty accept so now we have such object Channel now we can close uh project settings next let's open Forest Optimizer and set object set object set Collision object type for our box collision and it is going to be Forest vegetation replacer now what it going to overlap let's open PCG graph or you're making this using your foliage if you're using a foliage you can just select your foliage and check what oh okay you don't need to check for simple foliage simple foliage is just World static but in PCG you can select an object type for your static mesh so we can select static mesh spawner and in Collision you will be able to see an object type in my case it's World Dynamic but sometimes it's World static so what I'm going to do I'm going to tell this box that it will find an overlaps with World static and World Dynamic so let's set response first let's set Collision response to all channels and set it to ignore so that we will disable every Collision for every other channels next we're going to set Collision response to Channel World static and it's going to be overlap and the same for World Dynamic and it's also going to be overlap and connect it now our box will overlap with our instances but we didn't have an event to handle it so let's create it let's make our setup function to return this box so let's add a return node and let's add a sequence here like this and after setup of this box has completed we will return this component let's call it box Collision now let's go back into begin play we have a setup here and it returns us a box Collision and let's bind some event let's bind event uh and we need on begin overlap uh where is it bind event overlap here it is bind event on component begin overlap connected and we will also need to bind bind vent on end overlab now we have to create an event so let's type create event for this one duplicate it and we're going to do the same for this one here we can select an already created function or event or we can generate a new event so I'm going to generate a matching event just typing on create a matching event and type uh make its name something like onbox d overlap and the same for here on boox De end overlap so now we have these two events that will be called every time that box overlaps with some with something but we don't need to use something we need to check whether it is a karial instant static mesh component or in your case it may be just an instant static mesh component so uh we're getting other component here and checking cting it to karch instant static mesh component and the same is going here other component like this okay what we're going to do next we're going to call some function that will replace uh some hierarchal instan mesh with some actor so let's create a function and call it replace instance with actor and another function called replace actor with instance so replace ector with instance no we're going to set up replace instance with ector each should have some inputs first input is going to be in which hierarchial instant static manage component we're going to do this so first input is going to be component of type KY all instance oh instance static meas component and the second input is going to be an index so that we will be able to know on which index we have overlapped some component okay we gonna check here uh first if uh a static mesh is over is replaceable so that we should replace it because for example in my Forest I have just decorative items like ferns for example like this it's not interactable and I don't care whether it is an nectar or is a static mesh it should just stay here but everything else here should be replaced so how we going to do that first let's open and let's we need to know what is the component we have uh different components like if you open a PCG you will see a lot of hierarchial static meshes here first uh static mesh components here first for example for one static mesh second is for second and so on you will have a hism for every static mesh for every different static mesh well and every hism contains a static mesh that it instances so we want to check the static mesh so let's go here and get static mesh for current hism that we have overl and let's get object name object name is a unique name so it will be a unique name for the static mesh now what I want to do I want to have a data table in which we will have a list of all replaceable instances and a nectar with which we can replace this instance so let's create a structure and call it s Forest instance a replacer for example and what it will have it will have just an actor of type actor that's it let's close it and let's create a data table uh data where is it data table and select this structure here Forest instance replacer okay DT Forest instance replacers let's open it up and we going to add some rows so what's going to be a row name a row name is going to be a static mesh name so for example I want at first I want to replace I don't know names of these bushes but for example this Branch so let's open our PCG and I have where I'm spawn in branches by the way here I'm spawn in branches and I have one static mesh and it is called SM Branch who that's cool name so here is a name I'm just copying it opening my data table and pasting it into your old name and I have to select a class by the way let's open Forest instance replacer and it should be not type of vector it should not be an object reference it should be a class reference save it open data table again and select a nectar with which we want to replace it it's going to be BP Branch for example in my case so every static mesh of type SM Branch will will be replaced with a nectar of BP Branch now let's open uh Forest optimizaton to do with this object name we're going to check if we have a row in this data table with the same name so let's get data table row names select a data table here it's going to be our DT Forest instance replacers and we have to check if one of the rows have the same name as an object name so do we have a contains we have contains but it will not give us okay we will check if it if it contains and if contains then we're going to get this row we're going to get data table Row the same data data table uh forest in Forest instance replacers and the row name is going to be this name so this object name c uh converted to uh name type and we will receive an out row and if we break it we will get an class of an ector that we need to spawn so let's spawn en actor spawn actor from class this class and spawn transform spawn transform is going to be the same as an instance transform so what we're going to do we have a component and we have an index over we have a his component and we have an index of an instance so let's get component no uh let's get component as a local variable here and let's get an index also as a local variable here and let's get instance transform at this index also in a world space and we will receive a transform warl transform of this instant that we have overlapped and connect it into spawn transform now we will spawn an actor at the same location as our static mesh that we have overlapped next thing that we need to do we need to remove an instance so let's copy component in the index paste it here and call remove instance and we should provide an index of course now that's it what we need to do we need to call this function replace instance with zector and we should do it on on boox did overlap so let's call this function connected we have to provide a component it's going to be in hierarchial instant static mesh and an index other body index otherb index is an index of an instance in this case so let let's add this component to a character Forest optim optimizor save compile and let's test it out now I think that our Branch should be replaced also let's run it in a viewport and I have few branches already I don't know what are these branches branch let me delete them I don't want nectors to appear here and I just type here a branch in my outliner so I will see if some of the actors will spawn now let's move into the forest and here it is here you see a branch and as you can see in outliner uh an Nector has spawned because I have overlapped an instance and we don't have an instance here so why we can pick up a branch and nothing is here one more Branch appeared also here is far we have one more Branch if I will move here and Nector has appeared and you didn't even mention some changes because it spawned with the same transform at the same location great so but it works only for branches now if you want to add it for example for a for a bush you're going to just open this you're going to just where is where I'm spawn spawning bushes here I'm spawning bushes you're going to static mesh spawner selecting one of static mesh copying it name like previously creating a new rle pasting it here and select an ector with which it want to be replaced yes is it is a routine work to put every actor here every static meas that should be replaced but it will save you a lot of time in future next next what we want to do is we want to replace an ector back to an instance if we are far so let's uh oh let's CH change a function replace actor with instance I don't know why I called it replicate replace replace actor with instance well what it should it have it should have a nectar to replace actor of type actor oops actor like this and let's call this function here also on box the tent overlap we we are not ending overlap with hism we're ending overlap with a nectar so just plugging here and as vctor goes here well now we should check whether this data table has any row with this actor so let's open our forest Optimizer and again we're going to get data table row names it is going to be uh our forest instance replacers and for each of these rows let's set for each Loop we going to read um read row so get row data table row get data table row here data table is going to be the same Forest instance replacers and the row name is going to be array element we're breaking out our row and we're going to check if this actor class is the same as an ector that we have ended overlap now so let's get actor it's our local variable and get class of the sector and check if they are equal well that's fine and if we have found one then we should end this Loop by the way so we don't need for each Loop we need for each loop with break maybe I can convert it to break like this unfortunately unfortunately I think that I can't so I'm going to just delete it and make for each loop with break or no we don't need for each loop with break we'll just continue here and after a returning from this function for each will stop working now we have found that for example yes we have such um an Nector to be replaced with an instance but we don't know what a hism to use so we have to have a variable here and let's make it hism and let's make it actor hiss and it's going to be a map so let's select an actor object reference even actor class reference and it is going to be a map so for every actor class we will have some hierarchial instant static mesh like this well we should get this actor here hiss and find we're going to find a value well with this map we don't even need to check a data table so we can just remove it we will need only this one so we're checking if this map contains a hism and if it is so then we're getting this hism and adding an instance if true we're adding an instance and we have to Pro to select it an instance will be added in World space and an instance transform is going to be an Nector actor transform get actor transform returns us transform in World space well after that we're going to remove destroy this actor so we are getting getting actor where is it and call destroy actor like this okay one more thing that we have to do here when our actor will be destroyed it will generate it may generate some end overlap event so at first actor cannot be destroyed Mally so we have to check whether we should replace the sector once more we should add the branch and we should replace it only if actor is valid as you can see is valid returns true if it's not null and not pending kill if it is pending kill already we are not destroying it compile save now we have to fill this map somehow let's go to replace instance with actor and here we're going to get actor hiss and add hism is our component and a class is a class of this spond actor so it's this class like this and that's it but we need to be sure that our actor is generating and overlap event so that our box that we have added is overlapping with our actor so how we going to do this let's open my BP Branch let's select my for example branch and it has a capsule I don't know why do I have this capsule here I'm going to delete this let's select my static mesh and check its Collision its Collision preset is set to block all Dynamic and its object type is World Dynamic that's enough so it should not overlap with Forest vegetation replacer it just should be a world dynamic or World static or if it is for example not World Dynamic but physics body you are going into Forest Optimizer setup function and here we're setting our box to overlap only with World static and World Dynamic you just replicating it and making it also overlap with the physics body but I don't need this I will leave it World Dynamic and that's it also you have to ensure that a static mesh for your branch for example branch in my case for your static mesh has some Collision so let me find my Branch I will go here copy it here here is my static mesh and I'm going to show simple Collision so here is my simple Collision for a branch well it's not that simple by the way but no problem so I have it if you don't have it you selecting collision and add box Collision for example and that's all you need so now let's test it out again it should work I'm not sure but it should so on the right side we don't have any branches spawned let's move a little bit closer and a branch is spawned now let's move far from it and end overlap didn't C by the way or it is cold but nothing happens let's open here and let's print what we're ending overlap with save compile okay we have a branch okay it doesn't overlap so let's select our branch and uh it should generate an end overlap event by the way for optimizable stop World static and World Dynamic it overlaps with them and my branch has its own Collision it is uh also Collision enabl should be at least cury only so no with no Collision it will not work and uh it seems like Forest vegetation replacer should be set to overlap so be sure that it is set to overlap and let's test it again okay I saw a branch and I moved away from a branch right I'm sorry so as you can see a branch is spawned I'm turning back and now it's not an instance oh okay and now it's not an actor actor is removed and replaced with an instance you cannot see any actors there so if I will pick it up it generates okay it looks like does it destroy my actor or okay replace sector with an instance is it replaceable with an instance let me check this out if it is a problem with an instance yes it is a problem with this function so I think that is valid is not a best check so what should we do we [Music] should we should be able to check if our object is should be replaced so let's create a new interface here it's going to be a blueprint blueprint interface and call it BPI Forest instanible let's open it up and let's say add a function called should be replaced with instance and it's going to return us a bull Boolean value of for example let's let's name it yes compile save and our Branch or any other things that you're going to replace or parent class should implement this interface maybe I'm going to change it in my um parent class and I'm going to call it BPI Forest instanible w why do I have to interfaces I need only first instance B okay I think that it's going to be second one Forest instanible compile and save now let's open an interfaces and we have to define a function should be replaced with instance well by default let's plug it yes and what we're going to check first we're going to check if it is valid if it is valid no yes if it is valid and we're going to check if self is valid that's going to be a first and for example for my BP resource I have for my BP resource it will be the only check but for example for my Branch if I have already started to pick it up then it's going to it's not going to work so I'm going to Define this function also in my BP Branch should be replaced with an instance I'm going to add call to parent function so it will call my BP resource and if a parent says that it can be replaced and my branch is not collected so where is my um and also what I'm going to add I'm going to add on this uh I'm not going to add anything here else but you may want oh no why I'm sorry I'm going to also check if is actor being destroyed and it should not it should be false so not Boolean and and connect it like this and it's that's uh a condition oops like this so now back to for optimizor and here on replace ector with an instance we should not check it like this we should get an ector and we should call this function of this interface should be replaced with instance and check if yes then we're changing it compile save and let's play now I have moved to branch and it wasn't replaced it wasn't replaced back to an instant by the way now what happens should be replaced with instance yes [Music] mhm let me open BP resource is not being destroyed and is valid then it should be replaced with instance how BP branch maybe oh I have such function here in BP Branch I will going to delete this start it and let's test it again now it is replaced with instance actor instance actor instance and if I am picking it up it's marked as it's being destroyed and then it's not replaced with an instance so that's it for this video we've made it with a branch but you can simply change it by just populating your data table so the only thing you need to do is to populate one data table and check collisions on your static meshes and it is much simpler than the previous system and hope it will help you thanks for watching
Info
Channel: Dengojaba
Views: 37,949
Rating: undefined out of 5
Keywords: unrealengine5, development, tutorial, game, ue5, unreal engine, multiplayer, coop, online, replication, system, fps, optimization, blueprints, instances
Id: GFzBoUeem74
Channel Id: undefined
Length: 42min 24sec (2544 seconds)
Published: Fri Dec 22 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.