Hi there,
My team and I are currently loading objects via the StaticLoadObject() function in a similar manner to Rama’s method, which can be seen here: A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums
Unfortunately, we’re loading in a massive amount of meshes and materials at once in some cases. Sometimes (though not always) we’re bringing this data into the engine from an external server, so preloading the objects isn’t going to be feasible.
Is there a more efficient, gradual method of loading that still allows frames to process and other actions to be taken by the user while things load in the background? Perhaps a multithreaded approach? Lastly (and this is a large ask, I know), it would be best if the solution was mobile friendly.
I’m certainly not asking for code…just a nudge in the right direction theory-wise. I’m not sure if UE4 supports loading like this by default or not.
Hey there, while I’ve not had experience in doing this in UE4, I did have a large project a while back that did exactly this (loading thousands upon thousands of assets in parallel).
I am going to assume that the render thread is being blocked by the object’s loading. So yes, you should try asynchronously loading in the objects / assets as it sounds like you are using a blocking loading function (i.e. one that ensures the object is loaded when the function returns, e.g. if you need to use it asap for a effect, or something on demand (ignoring the bad form of this, as it leads to app hangs)).
Here’s some good reads to get you going:
-
https://docs.unrealengine.com/latest/INT/Programming/Assets/AsyncLoading/index.html has examples
- Async | Unreal Engine Documentation
-
A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums (which will probably be what the Async namespace wraps)
Some pseudo of how i did the project that I spoke of earlier:
MainTick()
{
if(we have more to load)
{
collection.expand(x) //allocate space for worker threads, peek a reasonable number, or guess (this is an object delcared outside of this function)
for each worker thread as worker
{
If(worker is done with what we gave it OR has not been given anything)
{
give worker a chunk of objects to load
}
}
}
else if(we need to clean up)
{
clean up (ie reduce / shrink the collection, from any excessive space we alloc'ed from our guessing)
}
}
Use a task factory / worker approach (spawn some threads and give them a handful to work on)
.
I don’t know what your experience is with parallel programming. If you are relatively new, things to watch out for:
- Ensure any kind of containers you are using for this asset loading is thread safe (ie the container containing the list of objects to load, needs to be thread safe in order to remove items as its being populated, otherwise we’d have to wait for it to be completely initialized (might not be feasible depending on your methodology)
- Ensure you are not trying to use any of the objects before they are done being loaded
- The allocation of space (for the objects-to-be-loaded) before the threads are given their tasks helps speed things up and reduce programmatic complexity
- There will be a balance between how many threads to run / objects to load async, and how fast things are actually loaded, this will vary depending on the user’s hardware and (from your references) network connection. Start small, and slowly creep up, but keep it at a minimum.
- If you have a high number of tasks (i.e. objects to load) give the worker threads chunks of tasks, rather than loading a single object and returning.
Thanks, the async loading looks like what I need.