The new 3.0 MetaHumans: 40% performance gains? Tutorial inside.

5.4 is OUT!.. and Epic is keeping the MetaHuman blueprint component & basic locomotion animations exclusive to UEFN. I hope this is simply a misunderstanding on my part.

Script is complete. I even added optional functions for:
-copying bone weights to their parent bone, in reverse hierarchy order.
-deleting any Skeletal Mesh LODs before modification & regenerating them after. This might make higher LODs even more performant.

Once I finish untangling the rest of the corrective post processing & add the ability to read lists of bones from text files, the testing will begin!

:smiling_face_with_tear: Im so proud of my little MetaHumans. They crash the program every time if you try to do whats happening in the script with the gui. But with the script it never crashes. its so nice to just open a blank project, import metahuman & 1 click transform them into whatever I want. Not only will they have less bones. They will have more performant LODs, lighter anim BPs & near identical levels of fidelity compared to the original @ LOD 0.

2 Likes

Snag - when you edit vertex weights, it doesnt apply to higher LODs. So after script completes, LOD 1 2 & 3 have beyond repair weight profiles.

So i added additional function to delete LODs, load LOD settings & regenerate LODs. This slowed me down, but it added more versatility to the script. Iā€™ll probably use this script on all of my skeletal meshes; boiling them down to similar complexity & LOD conventions. It would help me create tiers of MetaHumans, like main char or NPC.

I have to question this whole thing:
The meta human licensing is horrible (like most epic free stuff) and what this gets you is no better than a dayā€™s worth of custom work - yet without any of the benefitsā€¦
But I guess its fine for UFN where you have no rights to anything anyway?

That said:

This should prbably work the other way around;
where you give it a mesh to sample, and any bone that doesnā€™t match is deleted.

That way at least in theory, you could rename the bones on the original manny to match the MetaHuman trash, process it, and get meshes that have everything except the old setup deleted (with new names).
Could go a step further and pull the XML skeleton definition out the engine retargeting to use the same engine generated files to process this too.

On the rest, maximum number of bone per vertex should be hard set to 4.
Thats how the static mesh pipleline enforced it until they messed with it specifically for meta humans, so rewinding that to the same limit would net you some more performance (when dealing with groups thats probably important).

Overall, even with 1 bone you have performance issues that are otherwise not present when using something like an alembic cache.
Thats mostly because of the stuff built into the skeletalmesh class. Its actually the reason why real games that have a real need for billions of animated instances use shaders to make it happen - and its sort of engine agnostic.
While Epic just does it worse than everyone else when it comes to performance, they also quite literally just dgaf - never have, never will - so I donā€™t know that the engine can even be classified anywhere on any performance scale of any sort against any other engineā€¦
And obviously what you attempt has a cost in anytjing you attempt it with. Billions of moving objects are expensive. Period.

So, basically, a crowd like the one you shared the image of should probably be exported to a DCC, merged into an alembic and re-loaded in engine anyway.

Another thing you can look into is to enable the animation sharing setup on the meshesā€¦ it would help you run something like 100 actual skeletal meshes with the basic 14 to 16 bone setupā€¦

Past that, the problem is again processing and ticks (each skeletal mesh having its own tick). So creating a manager for them would be a gain (probably outside the UFN realm, that I donā€™t really know).

1 Like

Thank you for the input. Iā€™ve learned a LOT since the first post in this thread & your history of forum posts has been a good source of breadcrumbs. I have to admit, my initial expectations for this script have changed & I realize how silly the parameters were for those early performance tests.

I resonate with most everything you said. I was trying to delete bones and edit weights in the editor like normal. But the skeletal mesh editor & skin weight editor crash very often when you try to modify too many things at once. This also goes for deleting & regenerating LODs. What should be an easy days work is not possible due to these crashes, my inexperience with these systems & my resistance to doing work external of UE. And the MetaHuman EULA is not of concern, as my script is usable on any Skeletal Mesh. Any character specific data is obtained externally.

And yes, once functional to my satisfaction, iā€™m going to make the script pull data from .csv file for ease of use & flexibility. Users could delete per list or whitelist/blacklist style as you described. Nothing metahuman specific in the script.

The weighted-bones-per-vertex issue: the LOD settings involved in my delete & regenerate LODs have fields for enforcing a cap on this. Beyond simply modifying LODs, there are options which enable LOD 0 to be modified by any of the settings in the LOD settings data asset. Thia includes enforcing max # influences :slight_smile: but the jury is out as to how this interracts with anim post processing.

In some cases, UE doesnt mind when I disrupt the bones used in a corrective bone animation. But manually deleting the bones opposed to including them in LOD ā€œbones to ignoreā€ causes broken spaghetti arms. Needs more testing to see if bone deletion is even neccesary. I wonder if excluding bones or setting max benefits in LOD settings provides the same performance.

And for plugins: I have tested the animation sharing plugin & the animation budget allocator (anim tick throttling) with positive results. Merging metahuman skeletal meshes works wonders for reducing ticks, but iā€™m weary of head function, morphs & inability to replace modular components at runtime.

I also can get the number of bones <254 to avoid 16 bit bone index. But iā€™m not sure if the concequences of that data situation are project wide or per asset. Cant get away with unticking 16 bit bone index in project settings thanks to the MH head having >254 bones up until LOD5. And I really donā€™t want to tackly head/face modificationā€¦

Thanks for the input, please keep it coming! :grin:

1 Like

The obly potential reason I can see for this is when a main (non parented, or ā€œleafā€) bone is removed.

Removing something like a clavicle, would indeed damage the rest of the arm chain.
It is a mostly useless bone that an LOD less than 0 can surely do without, but its also the main bone that starts off the arm chain.

On the other hand - deleting a hand bone (just for pun sake) - would keep the whole arm working up until the hand.

Now, some of the new skeletal stuff is indeed bad - to where you can have something that should be a leaf/additional bone but ebded up being included into the chain.

As an example imagine a bicep.
Say you want it to pop out when you curlā€¦
To do this, if you aplit the single bone humans have into 2, and set it up correctly, you can easily get the bulge to accentuate any time the rig curls (by popping out the juncion of the 2 bones).
Thats the $0.001 c way to do it, as it takes maybe 3 to 4 minutes to rig and weight paint - but obviously it also breaks everything apart as soon as you do something simple like enabling ragdollā€¦

And well, Epic is a big fan of the .0000001 c solution, so i can totally see situations where stuff like this is common.

The way to fix it is retargeting. You can peobably just map both bones to the same bone - and get rid of the bone.
Thats the same as just eating a bone and assigning its weight paint to another bone.

Assuming you retarget your animations or run them with the skeleton setup for real time retargeting, then it should not cause issues (aside from all the painstaking work to make it happen?)ā€¦

Aside from that, keep up the good work - and dont be afraid to take the whole thing out the engine into blender to analize things (or script bettter Python stuff!)

2 Likes

So it finally works, to the level that satisfies my standard for proof of concept.

For any Skeletal Mesh, this script can do the following:

  1. Delete bones
  2. Delete LODs
  3. Regenerate LODs
  4. Save LODSettings Asset Data to .txt
  5. Load LODSettings Asset Data from .txt

*Current supported variables: termination_criterion, max_bones_per_vertex, max_num_of_verts, num_of_vert_percentage, bone_list & bones_to_prioritize. More variables or criterion can be added by copy and pasting lines and changing name of variable.

So when it comes to using this Skeletal Mesh Multitool on a Metahuman, itā€™s almost complete. Once the .txt file is prepared, all you need to do is run the deleteBones(,) script. It will delete listed bones, reparent their skin weights per 2nd list and regenerate all LODS

Perfect, except the hands turn to crystals. Just need to experiment with what bones to add to priority list and with what weight #. Almost there!

I havenā€™t used MetaHumans yet, just fascinated by the attempt to work on performance and make this game ready. Since you have figured out the performance influence of bones, I suppose a lot of things that are now bone animated could be faked with transitions between normal / displacement maps (wrinkles, folds in hands, bone rotation on the lower arms.) Now this is all just a wild idea and Iā€™m not familiar with the MetaHumans setup but I know this is one way to do it alternatively. It reduces bone and vert count at the cost of shader complexity and / or memory usage.

I mean #(&%(@ this bone count is ridiculous, what is the face like?

875 bones in metahuman head with up to 12 bones per vertex

giphy

oh wow that doesnā€™t sound right at all. A quick google gives me 43 muscles in the face, animated by 875 bones? Iā€™d honestly expect the good old bone setup for the rough animation (1 for each eye, 1 jaw, 1 head, 1 neck etc) and do the rest with normal / displacement in the shader be it from texture to texture transition or procedural. 875 face bonesā€¦ where to start with this. Well thanks for looking into this problem :slight_smile: . Makes me wonder how they recorded Senuaā€™s motion so well, maybe a different system.

1 Like

You have to keep in mind that epic likes to do whatever feels normal x 20 or so in an effort to make it look like its a lot work (and to tank pefromance) :stuck_out_tongue_winking_eye:

In all seriousness though, the bones are used differently based on what rig you want to use - so the face having exorbitant amounts makes sense mostly due to their abhorrent work practices when it comes to animationā€¦ if they spent the $ for a serious rigger with a proven track record to have a look at it, theyā€™d probably have half the bones if evenā€¦ (but why bother when metahumans were essentially just given a bigger grant than a mega grant and are essentially still free work thag epic just ā€œgetsā€?)

The finger, having 22 when really 4 is all a human finger has (one of which is already overkill for a 3d model ehich should sport 3 max) makes little to no senseā€¦

Re senuaā€™s motion its a publicity stunt bs, obviously. They put a ton of $ into making a specific model for the game that was capable of expressing emotion. They probably got freebies (like special support) from Epic to use said model in the fake demo.
As far as grassy knoll you must admit, this is far more likely than what the video of the metahuman face bs thing tries to peddleā€¦
Particularly when you try it and it doesnt work :stuck_out_tongue:

@Some
You probably want to remove hand bones alltogether past lod3 or so.
At a distance of 15+ meters it shouldnā€™t matter too much what position a hand is in on a model. Chances are the whole hand is about 10 pixel wide anyway (and thats at 4k).

Ps: perhaps the LOD tris reduction could be more analytical?
As in, maintaining more or less detail based on the distance between the main vertex and the first vertex found traveling in the opposite direction of the Normal? (Should work ok for most tube like structures, so hands fingers, arms legs, etc.

  • donā€™t think its easily achievable via engine script, but it offers a lot of options im not previy to, so it could.
    If not, then the older system that epic bought out, before they got bought out and or replaced, offered reduction options that automatically accounted for mesh thickness or allowed using texture maps to define custom densitiesā€¦ wish i could remeber the name of itā€¦ had a duck as logoā€¦
3 Likes

Quite disappointing if that is the matter. In the near future I will dive into this topic because I will be depending on mocap libraries for a part. Using a library obviously it would need to be matched with a skeleton, so people expect a modern ā€œstandardā€ that is somehow also game ready. Anything else is a ton of work.

I have already researched markerless mocap for custom / procedural rigs, with nothing but 1 cheap webcam, and concluded even modern AI assisted solutions (DeepLabCut) expect synced camera recordings from multiple angles to use as source for 3D pose estimation, where I once assumed that to be just estimated from skeletal data + a single cameraā€¦ Meaning DIY mocap in 3D isnā€™t quite there yet, especially when you work with animals or custom objects!

Well a good modern example that high detail animations is possible in games would be the Horizon series, or Beyond Two Souls mocap (face too!!) that was released in 2013!! Different engines of course.

That would be context specific. Feel like there is performance to gain at 0 quality loss if you could procedurally remove detail based on context. Say when you want to attach clothing youā€™d optimally want 1 skeletal mesh adapted to how much detail you can see with gloves on (even that can be problematic). At 30 meters away it would still look weird when someone plays tennis without animated fingers (letā€™s say open hands, default pose). Itā€™s very much context and resolution based.

1 Like

The LOD Settings Data Asset that comes with the Metahuman already has many bones excluded in the ā€œBone Listā€ setting.

Bone List #/LOD
LOD 0 - 0
LOD 1 - 145
LOD 2 - 223
LOD 3 - 268

The problem is, this is not a problem. Itā€™s potentially an easier solution than deleting any bones at all. After experimenting with LOD deletion & generation, I noticed this Bone List removes bones, maybe fixes weights and maybe removes influence of corrective anims in some instances.This ā€œwooshingā€ away of the bones per LOD, with such great results, feels too good to be true.

Going to experiment with this LOD Settings Data Asset list now; in combination to the raw delete-bones script I made. The script already loads and unloads a .txt bone list, so thatā€™s easy. Even if this easy solution invalidates most of the work I put into my script, Iā€™m still better off in the long run.

& I can maintain fidelity in chosen areas, such as the hands, by inlcuding weighted bones into the Priority List, which defends against LOD reduction settings by a variable amount. Should work nicely to keep the structure of certain areas. Iā€™m still not sure how to make the tri/vert reduction more rounded shape and less rock-like.

1 Like

Thanks for the detailed analysis, relaly appreciate this :slight_smile:

1 Like

Depending on reduction, angle based would need a lower angular value.
Decimation based uses a fixed standard instead, so just a lesser decimated value would reduce the effect - but since it doesnt look at the angle, it will still end up ā€œrock likeā€.
Are those oprions even avaliable in there?

No. Here are all of the options:
Iā€™ve tested them all. Then only helpful one not used is bones to prioritize. Reduced degeneration in that area but it requires specific bone names and fine tuned number; annoying.

Thats odd. Its something rather trivial to do with Blender - or even with the origibal reduction system that the engine incorporatedā€¦
I wonder if its a result of skeletal mehses being overhauled of whatā€¦

1 Like

Quick update: Iā€™ve been doing performance testing between deleting bones & LODing them with Skeletal Mesh LOD settings data asset.

Deleting bones provides the exact same performance result as phasing them out in the LOD data asset settings for the skeletal mesh. This is both a good thing and a bad thing.

The good:

8% Frame time reduction on scene with 35 LOD 0 Metahumans. Just by deleting extra finger bones that you will not notice are gone. Bone deletion works on LOD 0, but bone LODs only work for LODs >= 1. I need to do animation testing to make sure that the deletion of the bones in the hand can be done safely without the need to retarget anims.

Bone LODs are very powerful. I donā€™t have to worry about vertex weights being lost midair and then automatically being stuck to the root bone, breaking everything. Itā€™s less risky than deleting bones, but you can only affect LOD one and above. They have allowed me to continue further in this effort. Without snapping my brain in half with more python.

The script has allowed me to test different settings. Much faster with zero crashes. Whether you want to delete bones or try different bone LOD settings, this script will save you a ton of time. You can delete bones, replace vertex weights, save bone LOD settings & bone lists (of bones to phase out per-LOD) to .txt file, load said list of bones and settings into the unreal asset with 1 click. So during my testing I was trying to phase out many different kinds of bones using the LOD settings. Thanks to my script, all I had to do was copy the name of the bone from the tree and paste that name into txt file. After saving, I, type one command into the python console and the LOD settings data asset inside of unreal engine gets loaded with the entire list of bones. For every single LOD for as many LODs as you need.

The script is good to learn from if you want to do python in unreal. I had to do simple things such as Iā€™m getting reference to an asset in your content browser all the way to modifying. Editor properties and stuff with literally zero documentation. So you will probably be able to learn something if youā€™re used to reading code. I implemented txt file settings for termination criteria. Maximum percent of vertices. Maximum percent of triangles, whatever you need, you could easily look it up and just replace two words and pretty much inject any settings into any asset you want to.

Itā€™s good for my ego. Because all of the time I spend making these scripts has not gone for nothing! :crazy_face:. Iā€™ve decided Iā€™m ustmake one big video where I show all of the stuff that I found that can optimize the MetaHuman or any other skeletal mesh. People can take it and run with it. Most of the information will be complete, but some of it will be incomplete leads for info purposes.

The bad:

After modifying the skeleton bones or weights, You have to reweight or regenerate the skeletal mesh LODs. Luckily this has been automated in unreal engine for sometime, but the results are barely passable. This is my biggest concern. The Meta human, when freshly imported, comes with 4 LODs, and they are beautiful symmetrical. Nice curved vertex arrangement so the body folds nicely. But iā€™m sure these LODs were not generated inside of UE. The default LOD settings have LOD 1 with a vertex % of 1, Which would make the geometry not reduced at all. My script has a function called flushLODs, which deletes all of the LODs & regenerates them based on your settings. So I have been able to retest extremely fast, yet I have not found one setting that allows the metahumanā€™s regenerated skeletal mesh LODs to look anything better than gravel. See my above posts for visual understanding. There is a setting for ā€˜bones to prioritizeā€™ which can reduce geometry reduction around specific bones when generating LODs. The problem is I want to delete as many bones as possible. So I canā€™t prioritize a bone at a high LOD if Iā€™ve already deleted that bone at a lower LOD. I feel I am forced to strike a balance between the ease of deleting bones and the bad result of autogenerated LODs.

The head. Donā€™t really need to say much about this one. Itā€™s merely just a big unknown. Iā€™m not concerned with compatibility as there is a setting that maintains geometry complexity around breaks and seams in the mesh. So when iā€™m regenerating all of these meshes for the metahuman, their body parts still match at high LODs. I might pop back into the fortnite editor to see if I can figure out exactly what face bones are being disabled with the UEFN exclusive meta human optimization tool. If I canā€™t find an easy solution to layer on top of the ones I currently have, iā€™m not gonna spend much time on the head or face at all. The hair performs well enough with cards & The face still looks beautiful at LOD 3. Worst case scenario I crank up the head LOD & no one is the wiser. I could use the script to create a second head for NPCs, with little or no function. Some of the catch-all solutions that have been proven to work via plugins should allow me to curb some of the performance cost of the face and head without getting stuck in the weeds for another three months.

There are diminishing returns when it comes to deleting bones. For example: I can delete all sorts of corrective bones in the left side of body and get (X) ms decrease. But when I add the right side duplicates to the delete list, I get less than (X*2) ms decrease. This is also observed when stacking the many modifications & plugins on top of one another. I can understand this scenario happening if I stack a plugin on top of bone deletion, as less bones existing is going to make a skeletal mesh optimization plugin work for less things. I guess deleting bones is only teasing at the many skeletal mesh related tasks slowing down the game thread.

My final solution is going to include many different settings, plugins and modifications. I still need to test the bones per vertex setting. Hopefully, itā€™s a nice little sprinkle on top of performance. Iā€™m looking forward to finishing this soon. Like I said, Iā€™ll make a cute little youtube video when im satisfied; showing the latest Metahuman optimization techniques.

2 Likes

Closing in on the end of this project. I have free time coming up I will spend on concluding this story, regardless of the ending achieved. Here is what the current process looks like as labor:

  • download 2 .txt files to a folder, type bones you want to delete in 1 of them
  • open new UE project (Version >= 5.3, skeletal mesh editor required)
  • setup environment: settings, plugins, filters, auto save off & editor windows.
  • import skeletal mesh
  • save project (pre step1 save)
  • click their LOD Settings Data Asset
  • type ā€œskel.loadLODSettings()ā€ in Python console
  • open & close skeletal mesh asset, click yes (removes bones of choice from LODs >=1)
  • optional - regenerate LODs of choice: ā€œskel.regenerateLODs()ā€
  • add logic to post process anim bp (ā€œremovesā€ bones from LODs >=0)
  • confirm results (rotate bones to observe geometry changes & test performance as desired)
  • happy = save, test & move onto step 2
  • not happy = load from save

Going to finish up soon and get on with my game lol

3 Likes