diff --git a/Source/CharacterPlugin/Private/VirtualHuman.cpp b/Source/CharacterPlugin/Private/VirtualHuman.cpp
index f82ff653b7b93d13930d189d05e3b0007cefbfa8..23d52b2b4fa358e70c549837d68d6d92f5e97281 100644
--- a/Source/CharacterPlugin/Private/VirtualHuman.cpp
+++ b/Source/CharacterPlugin/Private/VirtualHuman.cpp
@@ -6,6 +6,7 @@
 #include "VirtualHumanAIController.h"
 #include "Engine/Engine.h"
 #include "CharacterPluginLogging.h"
+#include "HairStrandsInterface.h"
 
 AVirtualHuman::AVirtualHuman()
 {
@@ -36,6 +37,19 @@ void AVirtualHuman::BeginPlay()
 	// constantly seed the random stream so we don't have cluster syncing problems
 	// but seed it with the name of the VH, so random behavior is different for every VH
 	IdleRandomStream = FRandomStream(TextKeyUtil::HashString(GetName()));
+
+	// Ensure all mesh components tick no matter if they are rendered
+	// THis fixes de-synced animations on different cluster nodes
+	if (FModuleManager::Get().IsModuleLoaded("DisplayCluster")
+		&& IDisplayCluster::Get().GetOperationMode() == EDisplayClusterOperationMode::Cluster)
+	{
+		TArray<USkeletalMeshComponent*> Meshes;
+		GetComponents(Meshes, true);
+		for (USkeletalMeshComponent* M : Meshes)
+		{
+			M->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones;
+		}
+	}
 }
 
 // Called every frame
@@ -243,7 +257,7 @@ void AVirtualHuman::SetUpBodyType()
 		UObject* face_skeleton_obj = AssetLoader2.LoadSynchronous(AssetRef2);
 
 		if (root_obj != nullptr && body != nullptr && body_skeleton_obj != nullptr && face != nullptr &&
-		    face_skeleton_obj != nullptr)
+			face_skeleton_obj != nullptr)
 		{
 			USceneComponent* root = Cast<USceneComponent>(root_obj);
 			USkeleton* body_skel = Cast<USkeleton>(body_skeleton_obj);
@@ -332,7 +346,9 @@ void AVirtualHuman::PlayRandomIdleAnimation()
 			IdleAnim, "CustomIdleSlot", BlendTime, BlendTime);
 		// start timer for next random pick (make it a bit shorter to allow for blending, but only by a defined minimal amount for the animations)
 		GetWorld()->GetTimerManager().SetTimer(NextIdleTimerHandle, this, &AVirtualHuman::PlayRandomIdleAnimation,
-			DynamicMontage->GetPlayLength() - fmin(2.0 * BlendTime, (DynamicMontage->GetPlayLength()) * MinBlendTime), false);
+		                                       DynamicMontage->GetPlayLength() - fmin(
+			                                       2.0 * BlendTime, (DynamicMontage->GetPlayLength()) * MinBlendTime),
+		                                       false);
 	}
 	else
 	{
@@ -357,4 +373,4 @@ void AVirtualHuman::OnConstruction(const FTransform& Transform)
 {
 	Super::OnConstruction(Transform);
 	SetUpBodyType();
-}
\ No newline at end of file
+}