So, as the title says, im working on a multiplayer game where each player joins the session with auto spawning a weapon in their hand (so also auto attaches it).
Now the weapon is by default rotating and has a particle system on it, when it gets equipped, it gets disabled, both rotation and particle system, everything works as it should, except the RotatingMovementComponent can not be disabled during RepNotify since it runs way too early.
The only way I could make it work, is to add a timer and re-activate it and immediately deactivate it, this stops it, but since it depends on a timer, its not consistent for all clients and some clients that join even later, somehow still see the weapon rotating in the other character’s hand.
I have looked into the engine files, and I realised that the function I run for clients who join later (RepNotify) somehow runs so early, that it acts as a “Constructor” or “Construction function” for the components. So, you cannot run SetComponentTickEnabled there, has no effect, but since we know that it acts as a constuctor, the .bCanEverTick = false works! And of course, that means, that later we cant ever re-enable the rotation.
//note - runs so early, that it acts like a construction function, so can not run all runtime functions here like SetComponentTickEnabled
void AGCharacter::OnRep_WeaponSlot1()
{
if(WeaponSlot1)
{
WeaponSlot1->SetOwner(this);
WeaponSlot1->EquipWeapon();
WeaponSlot1->AttachWeapon(GetMesh());
// WeaponSlot1->RotatingMovement->Activate();
// WeaponSlot1->RotatingMovement->StopMovementImmediately();
// WeaponSlot1->RotatingMovement->Deactivate();
// WeaponSlot1->RotatingMovement->SetComponentTickEnabled(false);
// WeaponSlot1->RotatingMovement->PrimaryComponentTick.bCanEverTick = false;
// WeaponSlot1->RotatingMovement->PrimaryComponentTick.bCanEverTick = true;
// WeaponSlot1->RotatingMovement->SetComponentTickEnabled(true);
// WeaponSlot1->RotatingMovement->Activate();
// WeaponSlot1->RotatingMovement->RotationRate = FRotator(0.f,0.f,0.f);
GetWorld()->GetTimerManager().SetTimer(TestTimer, this, &AGCharacter::TestFn,0.1f,false);
// GetWorld()->GetTimerManager().SetTimer(TestTimer, this, &AGCharacter::TestFn2,5.5f,false);
UpdateHUD(WeaponSlot1, EQuippedWeaponSlot::WeaponSlot1);
}
}
and some test functions to check if i can later re-enable rotation:
void AGCharacter::TestFn()
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Orange, *FString::Printf(TEXT("TestFn")));
WeaponSlot1->RotatingMovement->PrimaryComponentTick.bCanEverTick = false;
GetWorld()->GetTimerManager().SetTimer(TestTimer, this, &AGCharacter::TestFn2,5.5f,false);
// WeaponSlot1->RotatingMovement->SetComponentTickEnabled(true);
// WeaponSlot1->RotatingMovement->Activate();
// WeaponSlot1->RotatingMovement->Deactivate();
}
void AGCharacter::TestFn2()
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Orange, *FString::Printf(TEXT("TestFn2")));
WeaponSlot1->RotatingMovement->PrimaryComponentTick.bCanEverTick = true;
WeaponSlot1->RotatingMovement->PrimaryComponentTick.SetTickFunctionEnable(true);
// WeaponSlot1->RotatingMovement->SetComponentTickEnabled(true);
// WeaponSlot1->RotatingMovement->Activate();
// WeaponSlot1->RotatingMovement->Deactivate();
}
So, I tried lots of things, none of them worked fully, the only thing that got closest to “act” like its working, is to set RotationRate to a 0 Rotator, but that means the component still rotates at every tick, just at 0 rate, so not really a solution.
Defaults:
RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingMovement"));
RotatingMovement->RotationRate = FRotator(0,180,0);
RotatingMovement->PrimaryComponentTick.bCanEverTick = true;
RotatingMovement->SetIsReplicated(true);
What can we do to fix this? Maybe set rotation rate to 0, then with a timer, deactivate it later? This way the client cant see it moving, and it actually gets deactivated later. Will try if it works.