Working on a multiplayer platformer wherein the players will be able to jump up through some platforms. The idea I had was that certain actions (jumping, double tapping downwards, etc) would put a pawn into ‘passthrough’ mode, that is, change the collision response of that pawn to a certain channel, on which those platforms exist, from block to overlap.
With the code I have, it works great locally. However, when testing it out networked (via the multi-client feature in the editor), the movement of remote players is erratic when jumping through platforms, as their mesh flits around the item they’re jumping through.
Is there a piece I’m missing?
SidescrollerCharacter.h
class ASidescrollerCharacter : public ACharacter
{
...
UPROPERTY(Replicated)
bool bShouldGoPassthrough;
UPROPERTY(Replicated)
int32 bNumOverlaps;
protected:
...
virtual void Jump();
virtual void Tick(float DeltaSeconds);
UFUNCTION()
virtual void OnOverlapBegin(AActor* OtherActor);
UFUNCTION()
virtual void OnOverlapEnd(AActor* OtherActor);
void SetPassthrough(bool bState);
UFUNCTION(reliable, server, WithValidation)
void ServerSetPassthrough(bool bState);
SidescrollerCharacter.cpp
... Inside the constructor
bShouldGoPassthrough = false;
CapsuleComponent->bGenerateOverlapEvents = true;
CapsuleComponent->bMultiBodyOverlap = true;
this->GetRootPrimitiveComponent()->bGenerateOverlapEvents = true;
this->GetRootPrimitiveComponent()->bMultiBodyOverlap = true;
OnActorBeginOverlap.AddDynamic(this, &ASidescrollerCharacter::OnOverlapBegin);
OnActorEndOverlap.AddDynamic(this, &ASidescrollerCharacter::OnOverlapEnd);
...
void ASidescrollerCharacter::Jump(){
ACharacter::Jump();
SetPassthrough(true);
}
void ASidescrollerCharacter::Tick(float DeltaSeconds){
ACharacter::Tick(DeltaSeconds);
if (this->GetVelocity().Z <= 0 && bShouldGoPassthrough){
if (bNumOverlaps == 0){
this->SetPassthrough(false);
}
}
}
void ASidescrollerCharacter::SetPassthrough(bool bState){
if (bState){
bShouldGoPassthrough = true;
this->GetRootPrimitiveComponent()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Overlap);
this->GetRootPrimitiveComponent()->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Overlap);
}
else{
bShouldGoPassthrough = false;
this->GetRootPrimitiveComponent()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
this->GetRootPrimitiveComponent()->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block);
}
if (Role < ROLE_Authority){
ServerSetPassthrough(bState);
}
}
bool ASidescrollerCharacter::ServerSetPassthrough_Validate(bool bState)
{
return true;
}
void ASidescrollerCharacter::ServerSetPassthrough_Implementation(bool bState){
SetPassthrough(bState);
print(TEXT("WOO"));
}
void ASidescrollerCharacter::OnOverlapBegin(AActor* OtherActor){
++bNumOverlaps;
print(TEXT("Begin Overlap"));
}
void ASidescrollerCharacter::OnOverlapEnd(AActor* OtherActor){
--bNumOverlaps;
print(TEXT("End Overlap"));
}
void ASidescrollerCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
//Replicate to all
DOREPLIFETIME(ASidescrollerCharacter, bShouldGoPassthrough);
DOREPLIFETIME(ASidescrollerCharacter, bNumOverlaps);
}