I have a level that is random gen and it can be various sizes. The problem is that the script that generates the ground and level details runs quite slow when you first hit play. It’s a construction script that spawns tiles in an NxN grid. Then at begin play some traces will determine tile features such as material, height, and what spawns on it.
It’s running plenty of circumstantial traces and collision checks to spawn things and it’s pretty slow, I can’t figure out what I would need to do to optimize that as I can’t really profile a load time?
Is there any way to optimize generation at play or am I stuck on long load times?
It’s honestly not that crazy maybe 500k meshes total on the largest map size.
And they are all HISMs, through testing it seems the tile setup(using multi-sphere traces) is the most expensive. Maybe some sort of way to only generate when the player is near?
Yes, I use a simple function that is a forloop x forloop to add instances of a scaled up cube to act as the floor.
So it’s all hisms with add instance should only be one draw call, isn’t that supposed to run super well?
On the largest map size it’s about 65k cubes and it gives me a good 2 minutes of lag to generate that with the other level details.(Which are all hisms generated randomly.)
I would assume assigning the materials and having a ton of the collision checks due to the traces causes a lot of lag. EDIT: Do you have an assign call for every floor material?
Okay so in the construction script the grid itself is pre-generated (No materials yet).
On begin play a spline path will go across the level anything it hits will be deleted and have a different tile type added. These different tiles will run a trace in a circle around themselves and delete any of the tiles that are the ones that are pre generated it.
Once all that is done a delay will wait 5 seconds and then materials will be added to these and the generation will randomly place actors depending on the tiles material. And that’s it.
Now if I unhook the last step completely it does not change the load times at all. Which causes me to think that for some reason the spline and traces are the main cause of lag, as well as the grid being pre-generated. As when you start out it is an empty level until you tell the game what level size you want. (Then it spawns the grid and drops you in.)
Since the player is already in the level when that last step happens anyways you get maybe a couple second stutter.(Which normally this would still be a load screen just haven’t implemented ti yet.)
Maybe this works for you: create an object channel for the pre generated grid. Then check a big enough area around the player for overlaps with those objects, and only spawn tiles there as the player moves through the level.
Honestly I’m not sure if that will work. I need some sort of way for my spline paths to be updated as that would generate as well as details till spawn on it.
This is more leaning into level streaming where the system I’m using is just 2 forloops spawning scaled up cubes in a grid.
You could add event dispatchers to your splines and call them when they have to be updated.
I mean, yeah this would be a rework on how your level is generated, but we have to reduce the number of operations on the second step. The amount of traces you fire is (presumably) in the tens of thousands. I mean, I’m sure you can make little improvements here and there, and that may even be enough to reduce the lag enough. But unless I know the code, I can only do so much. =)
You said you are using traces to delete grid tiles that are inside the range of newly created tiles? Do you have a separate tracing channel for the grid? Or do you filter by hit result?
I’m using a hit result from a sphere trace. It’s usually maybe 1-5 splines depending on the level settings which can equal anywhere from 25-2500 traces. The grid being pre-generated and the traces seem to be where most of the lag is coming from.
If I’m patient enough to actually wait on the largest map size the world runs perfect after everything is spawned in but that 5 minute wait is just brutal.
My splines will for loop through any hit tiles, if they match the tag their location will be added to an array, they are then removed and a different tile type will be put there, the splines work for things like roads, water, mountain ranges, walls, stuff of that nature.
The only cast is the hit component casts to hism so it know what it is dealing with.
Okay, I think I understand what you are doing now. The only actors in the scene, when you fire the traces, are the splines and the grid cubes? How many cubes do the traces usually hit?
At absolute most on the largest map there’s around 500k cubes give or take, the spline points will be in any location but at absolute most maybe 5k, then the traces off that would exponentially compound so maybe 10-15k are getting hit after that.
But on the smaller maps with only 500 cubes total it’s still giving me a good 30-45 second lag time and they would only be hitting like 25-50 cubes. It’s all hism so I’m not really sure where the lag is coming from, but it has to be this as it runs perfect after it’s all setup.
Perhaps you could get rid of the traces all together, and use maths to determine the instanced meshes indexes that would be hit. You could map every index to a 2D/3D vector to make it less complicated to set up.
Hmm. I’ve never heard it being done that way. Can you elaborate a little? Are you saying do that off the splines or just in place of them?
I really need some spline-esque type stuff that way I can generate a certain type on the hit and then another on the hits off of those tiles. Like a line with one mesh in middle and the edges are a different type.
Well, you can keep the splines. Make a struct (I’ll call it 2DV) consisting of two integers (x & y). Instead of firing a sphere trace you use the 2DVs to determine what tiles are in range. You use x and y of the centre position (as 2DV) and add/subtract the radius, then for each point within that square you check if the length of “Point - CentrePoint” is smaller or equal to the radius. If that is true the tile would be hit by your trace and needs to be removed. That means you can get the index that was mapped to that location and replace that HISM-Instance.
I’m sorry but I really don’t understand here. The x,y would subtract the radius then check if it’s center point is smaller then the radius?
I don’t really know how I would go about this so it would follow my splines. I’ve been testing all morning and I think I was initially wrong; the greatest tank on lag is just the grid generation I have setup. Let me get a screenshot for you.
This makes me think the only real solution is to generate as you go but I don’t know how something like that would work. Is it possible to have a set level size and make it generate as you go until you hit the edge?
You would calculate everything before spawning it, then spawn as you move through the level.
I hope this helps a bit, feel free to ask for clarifications.
EDIT: made a mistake in the first upload of the first screenshot.