Spawn 1 blueprint actor with 100s of static meshes, nested blueprints - Hitching

Hello,

I have been searching for a long time to try and get this issue resolved. Background: I have a procedural open world game, terrain, foliage etc… are all spawned in via way of voxel plugin. That part works fine. The issue I am having is trying to spawn one blueprint (a very large house) which has 100s of static meshes and other blueprints within it. Whenever I attempt to spawn this blueprint in, the game fps drops into the red, essentially a massive hitch even only if a second. This is very disruptive and obviously i would like to somehow spawn the item in over time instead of all items at once to avoid this. I do not know C++, everything is visual blueprints.

I have tried numerous plugins which use blueprints to expose threading to no avail. I have attempted to use async load class asset and this seems to do nothing, albeit I did not find many resources online to ensure I was doing this correctly (async load class asset, on complete, cast to the same blueprint class, spawnActor). Hoping that my blueprint is just incorrect and can be easily corrected.

Hope someone can help me figure out a solution as I have now started and stopped over 20 projects due to technical difficulties such as this one which seems to only be able to be solved by C++ knowledge. Appreciate any help.

1 Like

Take heart Maydie, almost everything can be done with blueprints.

Two ideas that spring to mind:

  1. Can you instance any of the meshes? Are they the same?

  2. Can you break this MEGA-print into many smaller blueprints?

Hi Clock. Thanks for the reply.

  1. There are some similar ones for sure, but the majority of them are nested blueprints that have multiple options to make modularization easier. Lots of unique assets. The ones that could be instanced are the walls and floors for example.

  2. I guess technically there is nothing stopping me from splitting the blueprints. My current workflow is to build the, house for example, in its entirety, then convert that into a single blueprint so that it can be spawned. It looks like I can for example put all the walls into one blueprint, all the books into another blueprint, furniture into another blueprint etc…by cutting them from the “mega” blueprint and pasting it to another blueprint.

The concern still remains though, I need to spawn each “child blueprint” as quick as possible via blueprints but avoid hitching. This would still happen trying to spawn multiple blueprints in quick succession. Is there anyway via blueprint to spread this task over time so it doesn’t try to spawn all the “child blueprints” in one shot?

Other options I’m thinking of ( seeing your description ) are:

a) Why spawn the whole building at once? The player can’t be outside and inside every room simultaneously ( I don’t know the structure ). You could spawn the outside, but only each room as they walk through.

b) Level streaming is another option. When you have the whole building constructed, before it’s converted to a blueprint, you could just draw level streaming volumes around various parts of it. That way, only the parts the player is in will be loaded at any one time.

Unfortunately, as you can see, having a lot in one BP is not a great way of doing it :frowning:

c) You can still convert the entire thing to a single static mesh, even after it’s a blueprint. It would take a few goes to get it right. Also, if you still had the building before you made it a blueprint, you could convert it to a mesh, and the engine will automatically instance any repeating meshes.

EDIT: Is it a proper house, like a mansion? Lots of meshes and blueprint doors etc?

EDIT2: Have you tried packaging it? It may not hitch then…

Appreciate you bouncing ideas off me.

essentially the voxel plugin spawns a single actor based on my noise setup. What it spawns initially is just an empty actor that communicates with a blueprint event manager. If conditions are met in the game, then it proceeds to spawn the “mega blueprint”.

a) It isn’t big enough for the effort of spawning and de-spawing the rooms. They are quite close. And once again there is the issue of spawning numerous blueprints in quick succession causing hitching. I don’t want to have to a delay between spawning, but maybe if there is a way to wait until the blueprint has successfully spawned before moving onto the next one? To be honest not sure how to go about it, there are no bools attached to that blueprint. Would have to think about that method for a bit.

b) I thought of level streaming, I did not know you could draw a level streaming volume at runtime. How would that work if you still have to spawn the actor which is the current issue?

Yeah, I think at the very least one thing to start with is breaking it down into smaller pieces. Doesn’t seem to be any way around that. I wish there was a method of looping through each component and spawning it that way. Completely different beast then having a blueprint baked into the level from the start.

c) I could try, I gather only half of them are static meshes that i could convert, the other half are essentially child blueprints with static meshes in them. You click a bool variable on the roof bp for example and it turns into a wider roof. It is possible I just may have forego this module workflow in favor of inserting as many static meshes to be converted and limit the nested blueprints.

I would say yeah more like a small mansion, lots of meshes and bluprint doors, windows, lighting etc…

Yup! First thing i did when i was experimenting with async loading and other plugins was to build it and try that out.

I think my solution is almost in sight. I think you are right that I should break it down as much as possible, but then the last part is trying to solve how to spawn each item but doing it over as many frames as possible. There must be something to check if a blueprint has successfully spawned and is loaded?

Ah:… enough info, maybe:

If you put the house together on a separate level and draw the level streaming volumes in the right place, later, you can stream an ‘instance’ of that level anywhere you want in your main level.

Because it has streaming volumes, it won’t totally load, just when you walk into a room etc.

This could work, but test it with a dummy house and levels first :wink:

I’m not 100% sure, but instead of using Async Load Class, try using Async Load Asset. I think when you load class, it doesn’t try to load static meshes in it, because components are not instantiated, it only loads the class default settings (UProperties), and with Async Load Asset, you will get all stuff loaded, because it will construct a CDO for the blueprint, construct all the static mesh components and load the meshes used by them. After that you can spawn actor via SpawnActorFromObject.

I might be wrong, but it’s worth a shot :slight_smile:

Just a snippet of insight. Meshes are read from drive and stored in memory on demand. If the mesh has LoDs they are loaded in ascending order. Low to high. As well as their materials. If each LoD has a different material (typical), then those are loaded in the same order.

e.g. Mesh 1 LoD 4 mesh, then material, LoD 3 mesh, then material etc until the last lod, then collision.

When you “Prefab” a scene all of it is needed when any part is called. Overall your telling your system to choke down all the pieces of a complex scene in one go. Whether this hitches or not depends on the hardware and overall performance of the platform doing the work. e.g. My PC vs Yours.

I’d profile the prefab, then take steps based on the results. Maybe materials are too complex.

Depending on usage I might attempt to use a trigger to spawn the interior deco. Slap one huge, or multiple trigger boxes/collision boxes around the main building and spawn deco/interactives via player overlap.

Just my 2 cents.

1 Like

I think this the the overall issue. Loading too much at one time.

Yes, it is the issue, but only if the loading happens in a synchroneous fashion (as in, when you try to spawn actor without pre-loading all the assets it uses), because sync loads happen on the game thread, so it have to wait till loading completes, and that waiting is the hitch. But if you do the async loading request, it won’t hitch, because all assets will be loaded in async loading thread.

This assumes that the process of Load, then spawn immediately is the problem. If loading to Memory from Drive is where the hitch happens, then pre-loading is moot.

Well, I’ll reiterate. The hitch is basically just observed game thread stall due to sync load. If you try to load large amount of data from disk to memory in game thread, you basically stop almost everything in your game till the load completes. But if you offload it to another thread via AsyncLoad request, your game thread won’t stall in waiting, which is the whole point of async loading.

1 Like

Gotcha. That makes sense.

Going to try the async load asset and will update you guys. I believe I tried it previously and nothing every happened. It went into the async load asset and never came out which was strange.

Stay tuned. Thanks everyone.

Edit: interesting. Unable to find spawn actor from object as shown in the screenshot. I even took off context sensitive…

Pull from the Async load Asset “Object” return, context on.

An alternative: Put an instance of this massive asset somewhere below the terrain in the level start area. This will force it to load when the level loads. The next instantiation that happens will be fast. It’s not a pretty solution, but it has been used in many shipping games …

Looks like this has to be done through editor utility actor or widget. I have never used this class before but will give it a go.

Nothing happens. Something must happen but nothing spawns. The printed text even shoots on screen.

Funny you should say that. I literally grabbed all the prefabs and all the static meshes and slapped them in one spot…no dice. Tried with the same blueprint. Still hitches.

I will also mention in case anyone asks: I am running everything on a nvme.2 drive, AMD Ryzen 9 5900X 12-Core Processor 3.70 GHz, 64.0 GB ram, nvidia rtx 3080ti. Which means if I am hitching this bad, I can only imagine what another computer will do with lower specs.

Interesting. I wonder if the hitch is the uploading of the assets to the graphics card, rather than loading from disk.

Try using a lower-level profiling tool to figure out what’s going on. Anything from NVIDIA Insight to Intel VTune could potentially give some specific kind of insight… there’s also the built-in section timings you could look at, although when the driver ends up stalling, it typically ends up making the time visible to the application show up on some mostly-unrelated place, like frame present, or shader bind …