So I created a shotgun weapon class which simply calls fireweapon several times in a loop to create a nice spread of pellets. It works great unless playing on a network client. When you do so there is a noticeable delay in the movement of the character. He stops moving for a brief moment as observed on the listen server, a judder in movement is observed on the client as well.
This does not occur in standalone mode, or on listen servers. How can I prevent this and still have a shotgun in my game?
Here is the Fire Weapon Code, taken from Shootergame
void ABBWeapon::FireWeapon()
{
if (MyPawn)
{
int32 RandSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandSeed);
float CurrentSpread = GetCurrentSpread();
float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);
FRotator UnusedRot;
FVector StartTrace;
FVector AimDir = MyPawn->GetBaseAimRotation().Vector();
MyPawn->Controller->GetPlayerViewPoint(StartTrace, UnusedRot);
StartTrace = StartTrace + AimDir * ((MyPawn->GetActorLocation() - StartTrace) | AimDir);
FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
FVector EndTrace = StartTrace + ShootDir * WeaponRange;
FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandSeed, CurrentSpread);
CurrentFiringSpread = FMath::Min(WeaponSpreadMax, CurrentFiringSpread + WeaponSpreadIncrement);
}
}
And then in a subclass for the shotgun FireWeapon looks like this:
void ABBShotGun::FireWeapon()
{
for (int32 i = 0; i < PelletCount; i++)
{
Super::FireWeapon();
}
}
Ideas?
EDIT: After more debugging, I discovered the culprit is the line ServerProcessInstantHit(Impact, Origin, ShootDir, RandSeed, AimSpread);
Which is located in ProcessInstantHit below. All it does is call ProcessInstant Hit on the server. But clearly calling an RPC 15 times in quick succession is too much of an ask for the networking system.
Any idea’s on how to make this faster?
void ABBWeapon::ProcessInstantHit(FHitResult Impact, FVector Origin, FVector ShootDir, int32 RandSeed, float AimSpread)
{
if (MyPawn && MyPawn->IsLocallyControlled() && GetNetMode() == NM_Client)
{
ServerProcessInstantHit(Impact, Origin, ShootDir, RandSeed, AimSpread);
}
if (Role == ROLE_Authority)
{
HitNotify.Origin = Origin;
HitNotify.RandSeed = RandSeed;
HitNotify.ReticleSpread = AimSpread;
}
if (GetNetMode() != NM_DedicatedServer)
{
SpawnImpactEffects(Impact);
}
// This actually deals the damage of the hit
if (Impact.Actor != NULL)
{
if (GetNetMode() != NM_Client || Impact.Actor->Role == ROLE_Authority || Impact.Actor->bTearOff)
{
FPointDamageEvent PointDmg;
PointDmg.DamageTypeClass = DamageType;
PointDmg.HitInfo = Impact;
PointDmg.ShotDirection = ShootDir;
PointDmg.Damage = Damage;
Impact.GetActor()->TakeDamage(PointDmg.Damage, PointDmg, MyPawn->Controller, this);
}
}
}