keywords: UE5, Groom, Hair, Fur, Performance Optimization

Cases

Dependency Module in Build.cs
PublicDependencyModuleNames.AddRange(
    new string[] { "HairCardGeneratorFramework", "HairStrandsCore", "HairStrandsRuntime", 
    "HairStrandsDeformer", "Niagara" });
How to change groom material at run-time

Add matertial slots in the Material tab of Groom Asset editor, then switch material by index.

if (AActor* Actor = UGameplayStatics::GetActorOfClass(this, ACharacter::StaticClass()))
{
	if (UGroomComponent* Groom = Cast<UGroomComponent>(Actor->GetComponentByClass(UGroomComponent::StaticClass())))
	{
		const TArray<FHairGroupsMaterial>& MatGroup= Groom->GroomAsset->HairGroupsMaterials;
		if (Index >= 0 && Index < MatGroup.Num())
		{
			if (UMaterialInterface* Mat = MatGroup[Index].Material)
			{
				Groom->SetMaterial(0, Mat);
			}
		}
	}
}
How to switch groom LOD at run-time

Add LOD group in the LOD tab of Groom Asset editor, then switch groom LOD by index.

UGroomComponent* Groom = ...;
Groom->SetForcedLOD(2);

If rendering groom as Strands, Groom->SetForcedLOD() will not work as expected (it will most likely disappear), because the GroomBinding asset doesn’t match the skeletal mesh’s LOD.
The safety way is to swith LOD of skeletal mesh, switching LOD of skeletal mesh will fire the LOD switching of groom asset automatically.

How to switch LOD of switch mesh at runtime?

SkMeshComp->SetMinLOD(SkMeshComp->GetNumLODs() - 1);

Performance Optimization

Groom Asset Settings

Reduce Curve Decimation and Vertex Decimation in Interpolation detail panel.

Disable Voxelize and Use Stable Rasterization in Strands details panel.

  1. Disable bCastDeepShadow in light component.

  2. Disable Voxelization: r.HairStrands.Voxelization 0.

Performance Optimization

Use Attach Parent Bound

Enable bUseAttachParentBound.

UGroomComponent::bUseAttachParentBound
How to disable or enable groom physics simulation at runtime
void SetGroomPhysicsEnable(UGroomComponent* GroomComponent, bool bEnble)
{
	if (GroomComponent)
	{
		if (UGroomAsset* Groom = GroomComponent->GroomAsset)
		{
			bool bIsDirty = false;
			for (FHairGroupsPhysics& HairGroupsPhysics : Groom->HairGroupsPhysics)
			{
				if (HairGroupsPhysics.SolverSettings.EnableSimulation != bEnble)
				{
					HairGroupsPhysics.SolverSettings.EnableSimulation = bEnble;
					bIsDirty = true;
				}
			}

			if (bIsDirty)
			{
				Groom->MarkPackageDirty();
			}
		}
	}
}
Asynchronous Loading

By default, loading groom bulk data from disk blocks the rendering thread, then rendering thread blocks the game thread, cause application hitching, especially on HDD.

Set GHairStrandsBulkData_AsyncLoading value large then -1 (the minimum LOD for async loading) to enable async loading.

Engine\Plugins\Runtime\HairStrands\Source\HairStrandsCore\Private\GroomResources.cpp

static int32 GHairStrandsBulkData_AsyncLoading = -1;
static int32 GHairCardsBulkData_AsyncLoading = -1;

static FAutoConsoleVariableRef CVarHairStrandsBulkData_AsyncLoading(TEXT("r.HairStrands.Strands.BulkData.AsyncLoading"), GHairStrandsBulkData_AsyncLoading, TEXT("Load hair strands data with async loading so that it is not blocking the rendering thread. This value define the MinLOD at which this happen. Default disabled (-1)"));
static FAutoConsoleVariableRef CVarHairCardsBulkData_AsyncLoading(TEXT("r.HairStrands.Cards.BulkData.AsyncLoading"), GHairCardsBulkData_AsyncLoading, TEXT("Load hair cards/meshes data with async loading so that it is not blocking the rendering thread. This value define the MinLOD at which this happen. Default disabled (-1)"));

Issues

Issue: How to fix the flickering in groom hair [UE4]

Enable Cast Deep Shadows in light actors.

Origin:
https://www.youtube.com/watch?v=4d7H3bEaXsw

Issue: The target skeletal mesh could be missing UVs
LogHairStrands: Error: [Groom] Binding asset could not be built. The target skeletal mesh could be missing UVs.
LogHairStrands: Error: [Groom] Binding asset could not be built. Some cards guide roots are not close enough to the target mesh to be projected onto it.
LogHairStrands: Error: [Groom] The binding asset (11_2_head_Binding) couldn't be built. This binding asset won't be used.

Reason:
The origins of the coordinate axes of the hair and the character are not match.
Need to assign the Source Skeletal Mesh when creating Groom Binding asset.

Groom disappears after assigning Binding Asset

Solution:

  1. Skeletal Mesh -> Skin Cache Usage -> Enabled.
  2. Project Settings -> Engine -> Rendering -> check Support Compute Skin Cache.

Origin: Unreal Engine 5 Groom disappears after assigning Binding Asset
https://www.youtube.com/watch?v=QunXwmuxAf0

Misc

References

Hair Rendering and Simulation
https://dev.epicgames.com/documentation/en-us/unreal-engine/hair-rendering-and-simulation-in-unreal-engine

Groom Asset Editor User Guide
https://docs.unrealengine.com/5.3/en-US/groom-asset-editor-user-guide-in-unreal-engine/

XGen Guidelines for Hair Creation
https://docs.unrealengine.com/5.3/en-US/xgen-guidelines-for-hair-creation-in-unreal-engine/

Create Hair in Unreal Engine 5 | Groom Tutorial Works in UE5
https://www.youtube.com/watch?v=gxp0FxyTflc

How to Create Hair in Unreal Engine 5 - Groom Tutorial
https://www.youtube.com/watch?v=ODkhcRvcaso

Groom (Hair & Fur), a brief overview of how Groom (hair & fur) works in Unreal Engine 4.
https://dev.epicgames.com/community/learning/tutorials/p4BG/unreal-engine-groom-hair-fur

Assets

Cyberpunk Hair is a groom game-optimized pack ready to a vast amount of styles
https://www.unrealengine.com/marketplace/en-US/product/cyberpunk-hair-for-game

Tools

Ornatrix UE5 plugin. Hair and fur editing suite inside Unreal Engine!
https://ephere.com/plugins/epic/ue/ornatrix/

gFur is a free shell based fur solution for Unreal Engine.
https://www.unrealengine.com/marketplace/en-US/product/gfur-5
https://github.com/GiM-GamesInMotion/gFurPro


In a group of many words, there is bound to be a mistake somewhere in them. -Chinese Proverbs