x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Multiplayer Projectile Hit Detection Problem

Hi, I'm trying to do Projectile Hit detection in multiplayer game. I'm using next approach:

  1. On the server side I'm saving all updated character's positions with world timestamp (PositionUpdated method).

  2. When client projectile Hit some character I'm sending Hit information to the server with server world timestamp (ServerCheckHit method). (All projectile fired only on clients on server we only check Hit's from client)

  3. On the server side I'm rewind character position to timestamp (GetRewindLocation method) and check position with Hit info (using simple sphere vs sphere intersection).

In some cases this approach working, but in some cases it has undefined behavior (please see screenshot attached "Lag Compensation Problem.png").

I can understand why rewinded serever position is different with client check position (the timestamps is equals). Please help me find where is the problem?

Thanks in advance, Alex.

Details:

CharacterMovementCompoenet.cpp

 void USCharacterMovementComponent::PerformMovement(float DeltaSeconds)
 {
     Super::PerformMovement(DeltaSeconds);
 
     if (CharacterOwner != NULL)
     {
         ASCharacter* SCharacterOwner = Cast<ASCharacter>(CharacterOwner);
         if (SCharacterOwner != NULL)
         {
             SCharacterOwner->PositionUpdated(); // Save character position for lag compensation
         }
     }
 }

Character.h

 ...
 
 /** Saved character transform for hit checking (lag compensation) */
 TArray<FSavedCharacterTransform> SavedTransforms;
 
 ...

Character.cpp

 void ASCharacter::PositionUpdated()
 {
     const float WorldTime = GetWorld()->GetTimeSeconds();
     if (SCharacterMovement != NULL)
     {
         new(SavedTransforms)FSavedCharacterTransform(GetActorLocation(), GetLookRotation(), SCharacterMovement->Velocity, WorldTime, SCharacterMovement->GetCurrentSynchTime());
     }
 
     if (SavedTransforms.Num() > 1 && SavedTransforms[1].Time < WorldTime - MaxLagCompensationSeconds)
     {
         SavedTransforms.RemoveAt(0);
     }
 }

 FVector ASCharacter::GetRewindLocation(float TargetTime)
 {
     FVector TargetLocation = GetActorLocation();
     if (GetWorld()->GetTimeSeconds() - TargetTime > 0.001f)
     {
         for (int32 i = SavedTransforms.Num() - 1; i >= 0; i--)
         {
             TargetLocation = SavedTransforms[i].Location;
             if (SavedTransforms[i].Time < TargetTime)
             {
                 if (i < SavedTransforms.Num() - 1)
                 {
                     float Percent  = (SavedTransforms[i + 1].Time == SavedTransforms[i].Time) ? 1.0f : (TargetTime - SavedTransforms[i].Time) / (SavedTransforms[i + 1].Time - SavedTransforms[i].Time);
                     TargetLocation = SavedTransforms[i].Location + Percent * (SavedTransforms[i + 1].Location - SavedTransforms[i].Location);
                 }
                 break;
             }
         }
     }
 
     return TargetLocation;
 }

 void ASCharacter::ServerCheckHit_Implementation(float TargetTime, const FHitResult& HitInfo, const FVector_NetQuantize& ShotDirection, ASCharacter* OtherCharacter)
 {
     if (OtherCharacter == NULL)
     {
         return;
     }
 
     if (Weapon != NULL && Weapon->CanFire())
     {
         FVector RewindLocation = OtherCharacter->GetRewindLocation(TargetTime);
         float   Distance       = (RewindLocation - HitInfo.ImpactPoint).Size2D();
         if (Distance < OtherCharacter->CollisionCheckRadius) // CollisionCheckRadius = 35; projectile sphere collision radius = 5; In some cases I'm receiving Distance > 60.0f (this is problem part) :(
         {
             // Take Damage
         }
     }
 }

Projectile.cpp

 void ASProjectile::ProcessHit_Implementation(AActor* OtherActor, const FHitResult& ImpactResult)
 {
     bool bIsOtherActorCharacter = false;
     if (OtherActor != NULL && OtherActor != this && OtherActor != Instigator && Instigator != NULL)
     {
         ASCharacter* OwnerCharacter = Cast<ASCharacter>(Instigator);
         ASCharacter* OtherCharacter = Cast<ASCharacter>(OtherActor);
         AGameState*  GameState      = GetWorld()->GetGameState();
         if (GameState != NULL && OwnerCharacter != NULL && OwnerCharacter->IsLocallyControlled() && OtherCharacter != NULL)
         {
             OwnerCharacter->ServerCheckHit(GameState->GetServerWorldTimeSeconds(), ImpactResult, GetActorRotation().RotateVector(FVector::ForwardVector), OtherCharacter); // Check this Hit on server using Server Worl time seconds
         }
 
         // Client impact logic
     }
 
     // Shutdown logic
 }

Lag Compensation Problem

Product Version: UE Github Master branch
Tags:
more ▼

asked Jul 11 '16 at 08:36 AM in Using UE4

avatar image

asherstnev
1 3 4 5

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

0 answers: sort voted first
Be the first one to answer this question
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question