Download

Multiplayer - click to move - Movement very slow and jittery

Hello, I’m making a multiplayer game. I used TopDownTemplate. PlayerController class is controlling movement. I have UFUNCTION(reliable, server, withvalidation) that client calls to move on server. This function on server calls UFUNCTION(reliable, client) to tell client to move. The client is super jittery and very slow. I don’t understand why, it’s the same code that was moving me just fine in single player.

Is it because my client rpc calls simplemovetolocation? I’ve heard that doesn’t work. I’ll try changing the implementation of the client rpc to something else to see if that works, but an answer would be greatly appreciated. I’ve just started making sense out of UE4 after a year or two of being flabbergasted by its complexity.

Could it maybe be something in another class than the controller? A setting in editor?


// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#include "MobaScapeServerPlayerController.h"
#include "AI/Navigation/NavigationSystem.h"
#include "Runtime/Engine/Classes/Components/DecalComponent.h"
#include "HeadMountedDisplayFunctionLibrary.h"
#include "MobaScapeServerCharacter.h"
#include "UnrealNetwork.h"

AMobaScapeServerPlayerController::AMobaScapeServerPlayerController()
{
    bShowMouseCursor = true;
    DefaultMouseCursor = EMouseCursor::Crosshairs;

    bReplicates = true;
}

void AMobaScapeServerPlayerController::PlayerTick(float DeltaTime)
{
    Super::PlayerTick(DeltaTime);

    // keep updating the destination every tick while desired
    if (bMoveToMouseCursor)
    {
        MoveToMouseCursor();
    }
}

void AMobaScapeServerPlayerController::SetupInputComponent()
{
    // set up gameplay key bindings
    Super::SetupInputComponent();

    InputComponent->BindAction("SetDestination", IE_Pressed, this, &AMobaScapeServerPlayerController::OnSetDestinationPressed);
    InputComponent->BindAction("SetDestination", IE_Released, this, &AMobaScapeServerPlayerController::OnSetDestinationReleased);

    // support touch devices
    InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMobaScapeServerPlayerController::MoveToTouchLocation);
    InputComponent->BindTouch(EInputEvent::IE_Repeat, this, &AMobaScapeServerPlayerController::MoveToTouchLocation);

    InputComponent->BindAction("ResetVR", IE_Pressed, this, &AMobaScapeServerPlayerController::OnResetVR);
}

void AMobaScapeServerPlayerController::OnResetVR()
{
    UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();
}

void AMobaScapeServerPlayerController::MoveToMouseCursor()
{
    // Trace to see what is under the mouse cursor
    FHitResult Hit;
    GetHitResultUnderCursor(ECC_Visibility, false, Hit);

    if (Hit.bBlockingHit)
    {
        // We hit something, move there
        SetNewMoveDestination(Hit.ImpactPoint);
    }
}

void AMobaScapeServerPlayerController::MoveToTouchLocation(const ETouchIndex::Type FingerIndex, const FVector Location)
{
    FVector2D ScreenSpaceLocation(Location);

    // Trace to see what is under the touch location
    FHitResult HitResult;
    GetHitResultAtScreenPosition(ScreenSpaceLocation, CurrentClickTraceChannel, true, HitResult);
    if (HitResult.bBlockingHit)
    {
        // We hit something, move there
        SetNewMoveDestination(HitResult.ImpactPoint);
    }
}

void AMobaScapeServerPlayerController::SetNewMoveDestination_Implementation(const FVector DestLocation)
{
    APawn* const MyPawn = GetPawn();
    if (MyPawn)
    {
        UNavigationSystem* const NavSys = GetWorld()->GetNavigationSystem();
        float const Distance = FVector::Dist(DestLocation, MyPawn->GetActorLocation());

        // We need to issue move command only if far enough in order for walk animation to play correctly
        if (NavSys && (Distance > 120.0f))
        {
            NavSys->SimpleMoveToLocation(this, DestLocation);
            setMoveDestinationOnClient(DestLocation);
        }
    }
}

void AMobaScapeServerPlayerController::setMoveDestinationOnClient_Implementation(const FVector DestLocation)
{
    GetWorld()->GetNavigationSystem()->SimpleMoveToLocation(this, DestLocation);
}

void AMobaScapeServerPlayerController::OnSetDestinationPressed()
{
    // set flag to keep updating destination until released
    bMoveToMouseCursor = true;
}

void AMobaScapeServerPlayerController::OnSetDestinationReleased()
{
    // clear flag to indicate we should stop updating the destination
    bMoveToMouseCursor = false;
}

bool AMobaScapeServerPlayerController::SetNewMoveDestination_Validate(const FVector DestLocation)
{
    return true;
}

You need to implement interpolation for simulated proxies.
Check out Zak Ms answer: https://answers.unrealengine.com/que…ement-for.html

Character class automatically replicates position and orientation when moved on server.
You telling a Client to move is conflicting with the already replicating movement, Server sees divergence on Character location then try to fix it then you move it again and Server tries to move it back to “correct” location again, this is why you see jittery.