For Developers Working With Unreal Engine

Patch Content Early – NOT At Runtime

by

I’m definitely in favour of allowing flexibility to game developers. I’d like to see a day where artists and designers don’t need to worry about end-platform performance. Sometimes, though, we can nudge things in the right direction.

Rules and guidelines are often laid out in development guides given to the development team… things like:-

  • Don’t use more than 8 textures on a material;
  • Don’t use textures bigger than 4096 x 4096;
  • Don’t use more than 80 bones on your characters;
  • Don’t use spaces in the “name” parameters on objects.

That last one is very common – and most old-school artists would follow this one regardless of whether it’s a restriction in the modern day or not. Personally, I prefer to see most of the restrictions taken out of guideline manuals by either:-

  • Fixing the root of the problem – eg. remove the restriction on spaces within names;
  • Not allowing the problem to happen – eg. don’t allow the content creator to add a space to names (note: existing content would still potentially need patching or fixing up);
  • Patching the problem – eg. convert the space to a “safe” character such as a dash (note: this can cause new issues – you could cause a duplicate and all manner of problems this way);
  • Warning the content creator about the problem – when the name is input, in a map check, at runtime…

Obviously, if you’re going to patch the problem or warn about it, ideally you should be doing that at the earliest point. Doing it at runtime, even when the patch looks simple, can cause performance problems.

So, leading into the finding for this report, we found two places in the Unreal Engine codebase where we were seeing very large numbers of allocations through string operations where bone names were being patched up if they contained spaces. Note that our project is very animation and character heavy – if yours isn’t, don’t expect to see the same ‘problems’ that we did.


The first of these is for FBoneReferences. These were showing up in our profiles with 7.7million short-term allocations (4.15gb) per minute. The problematic code was simply removing any spaces within BoneName by trimming any from the start or end. Recent optimizations to animation from Epic, in 4.10 and/or 4.11, have reduced the severity of this significantly – we’re seeing maybe 20-25% of these now.

Here’s the code, from SkeletalControl.cpp:-

bool FBoneReference::Initialize(const FBoneContainer& RequiredBones)
{
  BoneName = *BoneName.ToString().Trim().TrimTrailing();
  BoneIndex = RequiredBones.GetPoseBoneIndexForBoneName(BoneName);

And the change:-

bool FBoneReference::Initialize(const FBoneContainer& RequiredBones)
{
  check(!FString(BoneName.Contains(" ")));
  BoneIndex = RequiredBones.GetPoseBoneIndexForBoneName(BoneName);

The second optimization is with GetConvertedBoneName() in SkeletalMeshComponentPhysics.cpp. Again, Epic’s optimizations have helped somewhat. Currently, before optimizing, we were seeing around 60,000 short-term allocations (3.6mb) per minute.

// convert a bone name from APEX stype to FBX style
static FName GetConvertedBoneName(NxClothingAsset* ApexClothingAsset, int32 BoneIndex)
{
  return *FString(ApexClothingAsset->getBoneName(BoneIndex)).Replace(TEXT(" "), TEXT("-"));
}

Very simple to fix, we just change this to:-

// convert a bone name from APEX style to FBX style
static FName GetConvertedBoneName(NxClothingAsset* ApexClothingAsset, int32 BoneIndex)
{
  check(!FString(ApexClothingAsset->getBoneName(BoneIndex)).Contains(" "));
  return ApexClothingAsset->getBoneName(BoneIndex);
}

We also fixed up the code comment at the same time – the last time that I checked, APEX doesn’t support tampons (http://www.dictionary.com/browse/stype) – so converting from an “APEX stype” to “FBX style” doesn’t make sense at all. There’s another tampon reference in SkeletalMesh.cpp that could perhaps be plugged at the same time…


Hopefully, if these changes are picked up by Epic, they can add relevant editor-side or serialization code to fix/patch/warn about these earlier on. For our own project that’s not critical as the artists are pretty diligent…

Anyway, that’s it for this round! Please feel free to comment if you have a chance to try out this or any of our other optimizations – or even if you don’t.


Credit(s): Robert Troughton (Coconut Lizard)
Status: Currently unimplemented in 4.12


3 Comments

  1. Hey Robert,

    You’ve missed a bracket in check(!FString(BoneName.Contains(” “)). Don’t ask how I found out 😉

    Best
    Marcel

Leave a Reply

Your email address will not be published.

*

Latest from ALL

Trash Compactor

We recently found a huge leak in the UE4 garbage collector, particularly

Placating The Natives

In this article we delve into Blueprint Nativization, a relatively new feature
Go to Top
%d bloggers like this: