[TUTORIAL] C++ - Runtime Async Load Modular Character (Intermediate)

[TABLE]

Hi creasso. Thanks for explaining. I can see value in some form of async loading, although I believe that UE4 automatically handles loading with consideration to replication, level streaming, texture streaming, and LOD. It was mentioned that greater support for large worlds will be added. I translate this into loading large quantities of Assets with minimum performance/immersion breakage.

I’m building my games with Blueprints only. I’m having trouble locating FSkeletalMeshMerge or other mesh-merging (composition) equivalent in Blueprints. I believe mesh-merging would increase rendering performance in my GOLEM Construction System (which can be comprised of hundreds of meshes). In fact, I have use for Mesh Boolean operations: Union, Intersection and Difference dynamically during run-time. I’m aware its a tall order, dealing with texture issues pointed out here.

[https://arcadekomodo.com/home/wp-content/uploads/2014/11/gumballman_2_th.png

GOLEM(Click to Enlarge)](https://arcadekomodo.com/home/wp-content/uploads/2014/11/gumballman_2.png)

Does the code still work that way? i think they changed some things after 4.6. Some parts just doesnt work for me.

Great tutorial! You should put this on the Wiki too so people can find / link it easier!

Hey, Just wanted to say thanks for putting this up. It helped me.

@Jamsh I’m bad at formatting on wiki… :frowning:
If someone get interested into help with this and put it there I’ll be thankful.

To the ones making experiences with this method, I think something did change in 4.8 regarding async loading, but the code still works.

Best regards.

Hey,

Just a small correction to what you said for : " ID (I’m using int 32 to it) to don’t need doing searchs by strings"

FName exists for this exact reason, it internally stores an auto generated ID unique for that FName, therefore when you so say e.g : “Hand_01” == “Hand_02”, == operator is actually overloaded and it will actually just do an integer/ID comparison, rather than heavy string comparison ;-). The benefit I see for using FName over int32 is it will be more legible rather than artists, designers having to remember the integer ID.

Great tutorial btw :slight_smile:

Thanks

4.11.2 UPDATE (The MasterPoseComponent)

Well, the code worked until 4.10, so I did no updates.

I got a weird bug on my update to 4.11 regarding masterboneindexes, but I couldn’t find what was causing it.

By what I have seen, SetSkeletalMeshes now do a “pre” update regarding masterposecomponents (applying here on the Chest, Legs, Feet and Hands) and since we are assigning the MasterPose on Component creation, and the masterpose (HEAD) due to the async method will just be “filled” on runtime, sometimes the child meshes gets to update the masterbones “before” we ever have the Head mesh assigned what caused an invalid bone index.

Epic games programmers (THANK YOU!) already changed the code to prevent the “breaks” on try to access an “yet” inexistent MasterPoseComponent SkeletalMesh looking for bones, but on assign the head mesh, we need to ensure that every child “reassign” the async loaded head mesh as masterpose.

Please, on your Character_MultiPart.cpp update the void ACharacter_MultiPart:: DoAsyncHeadMeshChange() method as shown.

Cheers!

Awesome tutorial!

@creasso Thanks very much for that tutorial =)
One question though…
Merging the mesh gives me an advantage of lesser drawcalls, if using only one big atlas, it’s even only one drawcall.
In many games, I see, that you can tint your armor pieces, which is a nice feature. But having one big mesh, how to separately tint the correct areas, without loosing the one-big-atlas-only-1-drawcall_advantage?
There are mmo’s(no I don’t want to make one, just a good example^^), where are like 50 player and more on one place, with color tint feature. I don’t believe, that those models are separated to achieve independent colors for each part(boots,gloves, chest, etc…).

So how to solve this one?

I thought of using vertex painting, coloring the body/armor parts in a light greyshade and multiply the vertex colors with it.
It’s the only solution I can think of without increasing the drawcalls. The downside using this would being limited to the polyflow, let’s say a nice dragon layout on a chest and both shoulders, very detailed needs to be tinted, but not the rest of the mesh, I would need to rearrange the verts/quads in a way, that they are following the edges of the outlines, so the colors apply correct. That increases the tris count and may impact the skinning on the mesh.

Any ideas?

btw: My game won’t has more than 4 concurrently player, so if I plan to implement about 6 body peaces + 2 slots for weapons, should I just don’t care about the drawcalls? (8 slots x 4 player, so 32 more drawcalls max…)

@Zhentouk

I’m not used to the meshmerge process or how it does work on U4. But on watching most games (D3, Lineage II, Dark Souls) I can notice that characters are made from “parts”, while I don’t know if these meshes are merged post load the process on get these “per part” looks widelly used.

The “separated” texture to each part was simply a way to avoid to waste texture memory, as example, if you have 5 different parts on each set and the player is using one piece from each this lead to the game loading five 2048 tex to just use a part from that (one just the area where the boots are mapped, other just the chest, and so on), so is better get one 1024 tex by item and load just on demand.

About color swap or dyes, I would preffer make it by RGB mask (giving up to 3 pattern areas to change) and lerp, I think vertex color is “limited” specially if the details are small or really “detailed”.

Draw calls (not specialist) by what I see are “project sensitive”, there are too much noise on Internet about this or that “pro-tip” some applies always, some could have better usage just to mobile, after pay attention to what pros does (Skyrim, Lineage II, D3, Dark Souls, CHAIR and so on) I have seen all kind of things that “I” thought was wrong, but that on RL production is OK, I think it’s better you get a system that “works” to your game put your prototype running and after change/fix what gone wrong.

If we pay attention to Epic works they don’t wrote U4 without bugs, fixes, changes… It’s an “organic” process and they are “pros”. So why we put so much charge above our shoulders trying do it right at first try? :wink:

Best Regards, GL with your project!

@creasso

I think it merges the mesh with several submaterials. An rgb mask is a good idea, there are also rgba masks,
but I heared somewhere, the alpha channel is adding a bigger memory footbrint, so splitting my character into 3 meshgroups each with RGB mask would be allow to tint 9 parts of it separately.
Maybe I add another group for skin/hair/eyes. But these are on different materials by default mostly, so no RGB mask is needed I think.

Yes, I also think, the main difference between us and the “pros” is, the pros don’t care, they do, because they have no reference(or they are just confident) to an other instance above them(uber pros?^^), they are already the elite.
I will try it without atlassing it together first, and if I ever need a few more fps, then I tackle this one with mesh-groups and RGB masks. Cause I really love the freedom, each piece of armor gives me when I use a separate material.

Thanks for your detailed answer,

Best wishes and also good luck to your project =)

Does this work in packaged builds? I’m using a similar approach (DataTables, etc.), and all works just fine in the Editor, but not in packaged builds. Looks like it can’t find references to assets (in my particular case, Blueprints).

Hey guys! I know this tutorial is pretty old, but I’m trying to fit it in my code and some things I don’t get. To be precise I don’t understand how to spawn blueprint using async load.
In my case I have a DataAsset, containing number of blueprint refs (TAssetPtr<UBlueprint>) all derived from common AMyCharacter c++ class. I believe they are being loaded, but I don’t know what to do with them after I call ResolveObject() on FStringAssetReference. I tried Casting to different classes like AMyCharacter, UClass, UBlueprint etc. and using GetClass() or StaticClass() methods, sometimes combining all of the above, but nothing. Best I could get is empty AMyCharacter class actor (a checked the data with VS debugger and all customly created variables were empty), which ofcourse spawned nothing, since all character data is being set in the blueprints inside editor and not in c++.
I try to spawn it with GetWorld()->SpawnActor(), I used it before to spawn blueprints, which I loaded with ConstructorHelpers::FClassFinder(). It worked, but in case of async load it doesn’t and I don’t know what to do.

Ok, haha, as it often happens, after few days of futile attempts I tend ask a question on internet and after that I figure things out within next several hours by myself.

After Resolving Object I had to do the following:


( UClass*)(Cast<UBlueprint>(BlueprintAssetReference.ResolveObject()))->GeneratedClass;

This gives me desired class, that I then successfully spawn via GetWorld()->SpawnActor() method

Could someone post/upload a working version for 4.18?
I had to change several lines of c++ but it’s still not working, I think I messed something up. An updated version of the tutorial would be much appreciated =)
Thanks a bunch.

edit: sitting now 9+ hours, one compile error after another, so you don’t think I’m letting others do this work only. If I fix one error, there are 4 more other ones :S
This is too outdated for me to get this working anymore >.<

Can you post the source code that you have and I’ll help compile it

Hey Garner. Thank you. I just finished another c++ tutorial and found some information about the constructors in older Unreal versions that did change after 4.6.
If I can’t get it working until tomorrow, I’ll post my source.

Phew, I combined my authoritative UMyCharacter with this modular pawn c++ code and after a few changes, it compiles now.
There are some typos in the tutorial, but I understand, it’s a guide for advanced c++ users and I did it. I will test the actual char merge tomorrow.

Only thing I wonder is, after the CharacterMovement(inherited) in my character blueprint, there is another PawnInputComponent0 (Inherited).
I couldn’t find the line that was responsible for this one. If I already got authoritative character movement through derived “CharacterMovement” component, so I don’t need another one.

edit: the merging works, with animation =) And nvm. about the PawnInputComponent. It was always there, just didn’t reckognized it.

Here are some updates on this that i noticed.

TAssetPtr is still not deprecated, but it will be, and should be replaced with TSoftObjectPtr.

and TArray<FStringAssetReference> ObjToLoad; should be TArray<FSoftObjectPath> ObjToLoad;

and ToStringReference() should now be ToSoftObjectPath()

also TSubobjectPtr is deprecated, and you should use regular component pointers instead.

If anyone is still stuck ill post a updated version