Hello guys,
currently I’m spawning a bullet actor when a player shoots.
This makes it easy to simulate gravity and the travel speed of the bullet.
I “stress-tested” this by spawning a few hundred bullets with unlimited lifetime and I’m encountering a problem:
- Let’s say there are currently a few hundred bullets in the air.
- The player decides to shoot a wall.
- The bullets hit the wall and explode, but it takes very long for the client to see the explosion effects.
- The server sees everything correctly.
Now my questions:
- Why does it so long for the client to be able to see the effects but the server sees it instantly?
- Is there a more network efficient way to simulate bullet drop and travel time?
- How would I start?
Thanks for your time and help!
Edit:
My solution with the help of joeGraf
- Player Shoots
- I save the relevant properties
(FVector TraceFrom, FVector TraceTo, FVector Velocity, float DeltaSeconds, float ElapsedTime)
of every single bullet that is shot in a struct. - I call
SimulateShot(FVector TraceFrom, FVector TraceTo, FVector Velocity, float DeltaSeconds, float ElapsedTime)
that uses the values as parameters.
Here’s what I do in SimulateShot:
-
I use LineTraceSingleByChannel with TraceFrom and TraceTo
-
If the FHitResult is a bBlockingHit, I print which actor I’ve hit (I should and will probably call replication and damage here)
-
I change important values like that:
// Bullet Drop
TraceFrom = TraceTo;
TraceTo = (Velocity * DeltaSeconds) + TraceFrom;
Velocity += DeltaSeconds * ProjectileConfig.ProjectileDrop;
DeltaSeconds = GetWorld()->GetDeltaSeconds();
ElapsedTime += DeltaSeconds;
After that:
if (!BulletHitResult.bBlockingHit && ElapsedTime <= ProjectileConfig.ProjectileLifeSpan)
{
BulletTimer(TraceFrom, TraceTo, Velocity, DeltaSeconds, ElapsedTime);
}
DrawDebugLine(this->GetWorld(), TraceFrom, TraceTo, FColor::Red, true, 10000, 30);
I stop the trace as soon as ElapsedTime hits the intended ProjectileLifespan which I save in another struct,
and I call a function which was the trickiest part for me - BulletTimer:
void ASWeaponProjectile::BulletTimer(FVector TraceFrom, FVector TraceTo, FVector Velocity, float DeltaSeconds, float ElapsedTime)
{
FTimerHandle TimerHandle_BulletTimer;
FTimerDelegate BulletDelegate = FTimerDelegate::CreateUObject(this, &ASWeaponProjectile::SimulateShot, TraceFrom, TraceTo, Velocity, DeltaSeconds, ElapsedTime);
GetWorldTimerManager().SetTimer(TimerHandle_BulletTimer, BulletDelegate, DeltaSeconds, false);
}
I’m using a timer to call SimulateShot again every Tick
I haven’t tested this with high load yet but I think it should work since I don’t spawn any actors and the LineTrace gets stopped as soon as the ProjectileLifeSpan is reached.
I hope this is more network friendly and maybe my solution can help somebody with their problem or with other stuff.
It’s definitely not guaranteed to be in any way “good” or the solution.