Hello,
I will try to explain my problem as best as I can, given that it’s quite a strange one.
My multiplayer project is very simple at the moment. I have a character blueprint with C++ to control it’s movement logic and a custom player controller to send input to the character.
All the game mode does is spawn the default pawn.
It seems that only the server is able to control the character. All the clients, although they accept input (I can see that with a debug message on screen), their character does not move.
Replication is on for character blueprint and the “replicate movement” checkbox is ticked. I don’t see what different I am doing to the third person sample project which works correctly, even in dedicated server mode.
I am posting some of the player controller and character code, if it’s worth anything to you guys.
The controller:
void APlayerMechController::SetupInputComponent()
{
Super::SetupInputComponent();
// axis
InputComponent->BindAxis("Horizontal", this, &APlayerMechController::OnHorizontal);
InputComponent->BindAxis("Vertical", this, &APlayerMechController::OnVertical);
// buttons
InputComponent->BindAction("FreeRun", IE_Pressed, this, &APlayerMechController::OnFreeRunPress);
InputComponent->BindAction("FreeRun", IE_Released, this, &APlayerMechController::OnFreeRunRelease);
}
void APlayerMechController::OnHorizontal(float axis)
{
MechPawn = Cast<AMech>(GetPawn());
if (MechPawn != nullptr && axis != 0.0f)
{
MechPawn->OnHorizontal(axis);
}
}
void APlayerMechController::OnVertical(float axis)
{
MechPawn = Cast<AMech>(GetPawn());
if (MechPawn != nullptr && axis != 0.0f)
{
MechPawn->OnVertical(axis);
}
}
And part of the character movement code:
void AMech::BeginPlay()
{
Super::BeginPlay();
UCharacterMovementComponent* MovementCmp = Cast<UCharacterMovementComponent>(GetMovementComponent());
OriginalWalkSpeed = MovementCmp->MaxWalkSpeed;
CurrentHorizontal = CurrentVertical = 0.0f;
CurrentRotation = GetActorRotation();
}
AMech* AMech::FindEnemy()
{
for (TActorIterator<AMech> It(GetWorld()); It; ++It)
{
if (*It != this)
{
return *It;
}
}
return nullptr;
}
void AMech::OnHorizontal(float axis)
{
CurrentHorizontal = axis;
OnAxisUpdate(CurrentHorizontal, CurrentVertical);
}
void AMech::OnVertical(float axis)
{
CurrentVertical = axis;
OnAxisUpdate(CurrentHorizontal, CurrentVertical);
}
float AMech::GetForwardSign() const
{
FVector Fwd = GetActorForwardVector();
FVector CamFwd = Controller->GetViewTarget()->GetActorForwardVector();
FVector Perp = FVector::CrossProduct(Fwd, CamFwd);
return Perp.Z > 0 ? -1.0f : 1.0f;
}
void AMech::OnAxisUpdate(float horizontal, float vertical)
{
if (Controller != nullptr) {
float dt = GetWorld()->GetDeltaSeconds();
UCharacterMovementComponent* MovementCmp = Cast<UCharacterMovementComponent>(GetMovementComponent());
FRotator CamRotation = Controller->GetViewTarget()->GetActorRotation();
FVector MoveDir(0,0,0);
// free running around the world
if (IsFreeRunning)
{
MovementCmp->MaxWalkSpeed = OriginalWalkSpeed;
float Angle = PI / 2.0f - FMath::Atan2(vertical, horizontal) + FMath::DegreesToRadians(CamRotation.Yaw);
FVector V(horizontal, vertical, 0.0f);
float Forward = V.Size();
float Strafe = 0.0f;
if (!FMath::IsNearlyZero(Forward)) {
LastTargetRotation = FRotator(0.0f, FMath::RadiansToDegrees(Angle), 0.0f);
}
MoveDir = GetActorForwardVector() * Forward;
}
// movement while facing the opponent + strafe
else
{
AMech* Enemy = FindEnemy();
if (Enemy)
{
MovementCmp->MaxWalkSpeed = OriginalWalkSpeed / 4.0f;
FVector LookDir = (Enemy->GetActorLocation() - GetActorLocation());
LookDir.Normalize();
LastTargetRotation = LookDir.Rotation();
MoveDir = GetActorForwardVector() * horizontal * GetForwardSign() + GetActorRightVector() * vertical;
}
}
CurrentRotation = FMath::RInterpTo(CurrentRotation, LastTargetRotation, dt, 10.0f);
SetActorRotation(CurrentRotation);
MovementCmp->AddInputVector(MoveDir);
}
}
I also have a camera blueprint which is living in the scene. This camera is just setting the view perpendicular to the 2 game characters. How I set the view target is using this (in the camera blueprint):
camera blueprint
I have noticed that when I do a “showdebug input” I only see input being collected by the Camera actor in the scene. Unless I am understanding this debug command incorrectly, how come the characters do get input?
I am sorry for the long post, I hope someone sheds some light.
Thanks!