From 28a90bb748e177ab6fb937e0d14763b1e4def4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=BChlem?= <kuehlem@vr.rwth-aachen.de> Date: Tue, 22 Apr 2025 10:09:34 +0200 Subject: [PATCH] fix: Set anim tick behavior for all VH related meshes automatically to avoid de-sync on NDisplay --- .../CharacterPlugin/Private/VirtualHuman.cpp | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/CharacterPlugin/Private/VirtualHuman.cpp b/Source/CharacterPlugin/Private/VirtualHuman.cpp index f82ff653..23d52b2b 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 +} -- GitLab