Download

C++ line trace is not accurate.

In the video https://youtu.be/6z03rtcFvVA as you can see when I aim at the head, I hit the “upper arm” and on the server of my other player, you can see the debug line is hitting the head and is constantly moving because of the animation. How can I stop this from happening? The game is never consistent as to where I aim. For my player I have this : (so you can get a sense of how my components are created and what is attached to what)


AFPSCharacter::AFPSCharacter()
{
SetReplicates(true);
SetReplicateMovement(true);

FPSCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FPS Camera"));
FPSCamera->FieldOfView = 120;
FPSCamera->bUsePawnControlRotation = true;
FPSCamera->SetupAttachment(GetCapsuleComponent());
FPSCamera->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("head"));

FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FPSMesh"));
FPSMesh->SetupAttachment(FPSCamera);
FPSMesh->CastShadow = false;
FPSMesh->SetOnlyOwnerSee(true);

GetMesh()->SetOwnerNoSee(true);

GunMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Weapon Mesh"));
GunMesh->CastShadow = false;
GunMesh->SetupAttachment(FPSMesh, "GripPoint");

TPGunMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("TPGunMesh"));
TPGunMesh->SetupAttachment(GetMesh(), "WeaponSocket");
TPGunMesh->SetOwnerNoSee(true);

//getMesh() is essentially the third person mesh.
}


could it be the way I connected these components and its throwing off the line tracing causing the constant strafing that we see on the client?

for fire I call these:


void AFPSCharacter::Fire()
{

if (Item && Item->bPickedUp) {
if (GetLocalRole() < ROLE_Authority) {
ServerFire();
UE_LOG(LogTemp, Warning, TEXT("Fire"));
}
}
}

void AFPSCharacter::ServerFire_Implementation()
{
if (Item && Item->bPickedUp) {
if (GetLocalRole() == ROLE_Authority) {
NetFire();
UE_LOG(LogTemp, Warning, TEXT("Server Fire"));
}
}
}

bool AFPSCharacter::ServerFire_Validate()
{
return true;
}



void AFPSCharacter::NetFire_Implementation()
{
if (Item && Item->bPickedUp) {
Item->Fire();
UE_LOG(LogTemp, Warning, TEXT("NetFire"));
}
}

//item fire:
void AItem::Fire()
{

//following tom loomans tutorial of shooting!

FVector EyeLocation;
FRotator EyeRotation;
EyeLocation = FPSCharacterRef->GunMesh->GetSocketLocation("MuzzleFlash");
EyeRotation = FPSCharacterRef->GunMesh->GetSocketRotation("MuzzleFlash");

FVector ShotDirection = EyeRotation.Vector();

FVector TraceEnd = EyeLocation + (ShotDirection * 10000);
FHitResult Hit;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(this);
//QueryParams.AddIgnoredActor(FPSCharacterRef->GetOwner());
QueryParams.bTraceComplex = true;

if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams)) {

AActor*HitActor = Hit.GetActor();
//if we hit a player we want to subtract the health from that player
UE_LOG(LogTemp, Warning, TEXT("%s"), *HitActor->GetName());

//if the hit actor IS an enemy player

UGameplayStatics::ApplyPointDamage(HitActor, DPS, ShotDirection, Hit, HitActor->GetInstigatorController(), this, DamageType);


}
DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1.0f, 0, 1.0f);


}

As you can see, it should be accurate everything is constant and im not sure why its so messed up. Some guidance would be nice, thank you

Welcome to multiplayer nightmare…
You should take socket location from client side instead, and pass that location to the server to fire the raycast.
Your sockets rotation/location on server are not exactly replicated.

But then… what if a cheater makes the socket always point to enemy head? Well, good luck :wink:

You need to look into a technique called lag compensation to solve this. It’s standard in pretty much every FPS. If you google it, the top result should give you a pretty good idea of what you need to do. Basically the idea is that you need to rewind time on the server so that it sees the same things the client did when it took the shot. Then you can do an authoritative hit scan on the server without any risk of hackers spoofing positions.

Thank you guys for the guidance! I’ll definitely do some research on this. Im very interested in lag compensation. But I don’t think I fully understand multiplayer yet to be able to do this but im down for the challenge.

Depending on what you’re doing, you might not need to be so in-depth. Sure, if you’re trying to make an actual release involving PvP you’d need this kind of functionality, but if you’re trying to learn the engine or make something to play with friends, I wouldn’t let it scare you off. Client-authorative methods should suffice for that sort of thing, e.g, the method Bruno pointed out in which the client passes information to the server for specific things that might not be replicated. Good luck – replication is a massive headache in general in my experience so far.