Download

How to make shotgun instant hit spread

I exploring the Shooter Game project->ShooterWeapon_instant. I am trying to grasp the logic of how to make it be able to produce a shotgun effect using multiple traces like a scatter shot. Any help would be appreciated.

heres the existing code I am examining

void AShooterWeapon_Instant::FireWeapon()
{
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
const float CurrentSpread = GetCurrentSpread();
const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);

const FVector AimDir = GetAdjustedAim();
const FVector StartTrace = GetCameraDamageStartLocation(AimDir);
const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange;

const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);

CurrentFiringSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentFiringSpread + InstantConfig.FiringSpreadIncrement);

}

Putting this bit of code in a for loop should do the basics of what you are after.



const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange;

const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);


Once you’ve got that working you’ll then fall down the rabbit hole of “why is only one particle effect appearing”, and then the issue of trying to “replicate all the data to the client” (if you are making a multiplayer game).

But this is the starting point :slight_smile:

It sounds like you went this road yourself hehe, did you ever got it working? I am in that rabbit hole atm and could use a rope ;D
Point me in the right direction!

I’ve been thinking about this a lot lately. I’m sure there are plenty of guides on how to do all of this, but here’s my take on it: come up with a formula that gives you the position of the projectiles at the point in time that you plug into it. This not only gives you deterministic projectibles, but you can also handle low-frame-rate situations more accurately.

Then every physics frame sample that formula and get the current position and check for any overlaps and do damage. If there’s nothing, then sample one tick behind and in front of the current frame and if there’s any overlap terminate the projectile and register a hit. This accounts for very thin surfaces or small objects (or even bullet penetration).

Bonus: you don’t need to create a buttload of actors, just manage the projectiles for that player in the pawn.

Here’s a good example of projectile math: https://www.omnicalculator.com/physi…jectile-motion

And here’s the graphing tool I’d use to test it: Graphing Calculator

Talking about projectile physics would be derailing this thread a bit though. The conversation here seems to be about how to replicate multiple impact effects for a trace weapon.

13tisa13 - Yes I got it working, and managed to use shared random variables so that a random spread on the server is the same as a random spread on the client.

The basics of it are -
Have a call on your weapon that starts the firing procedure
Do the loop that traces from the weapon, and make sure to initialize using


 FFOwner->SynchronizeRandomStream();
FFOwner->InitializeRandomStream(); 

When you use the randomizers for your spread use -


RandStream.FRand();

When all thats done, set a flag saying that the fire effect happened that replicates to all the clients Have the clients start a firing effect, and run through the same loop (using the same stream and RandStream.FRand() this time drawing the effects of the traces rather than applying the damage.

The shooter game will have an example of getting the effect to fire on the client. When you find it, thats your hook to trigger the visual effects. If you want something more specific post up some code and we’ll work through it.

Logging is your friend when it comes to client/server debugging -
implement the stuff in this link and spread it liberally through your code https://wiki.unrealengine.com/Log_Ma…ode_and_Colour

Hey, sorry for the wait.
I should explain better what I’m doing.
I’m new to C++ so I’m trying to figure out Shooter Example as a learning experiance and expand it to support multiple weapons.
In the making of shotguns I’ve set up the the option “Multishot” and “Number of shots” in base instant weapon.
Through log testing I figured out that “ProcessInstantHit” doesn’t replicate from server to clients.
Client sends “NumberOfShots” which replicate fine on Server, but from server to client only 1 impact effect is visible.
Here is the code;


void AShooterWeapon_Instant::FireWeapon()
{
//Switches Between Multiple and Single line trace
if (bIsMultiShot)
{
//Multiple Traces based on Spread amount are fired with one shot
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
const float CurrentSpread = GetCurrentSpread();
const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);

const FVector AimDir = GetAdjustedAim();
const FVector StartTrace = GetCameraDamageStartLocation(AimDir);

for (int32 Loop = 0; Loop < NumberOfShots; Loop++)
{
const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange;

const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);
}

CurrentFiringSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentFiringSpread + InstantConfig.FiringSpreadIncrement);
}
else
{
//Fire only one trace
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
const float CurrentSpread = GetCurrentSpread();
const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);

const FVector AimDir = GetAdjustedAim();
const FVector StartTrace = GetCameraDamageStartLocation(AimDir);
const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange;

const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);

CurrentFiringSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentFiringSpread + InstantConfig.FiringSpreadIncrement);
}

I’m not quite sure what’s stopping the effect from being called since they work with a single shot other then it can’t be processed that fast.
I also tested the same thing on Projectileweapon and replaced the explosion effect on the projectile with impact effect…that seems to work ok.
Since I’m new to C++ I’m not quite sure what the right approach to doing this right would be.
I’ll do some research on RandomStream you suggested cause atm I have no idea how to set this up.
Thanks for kicking me in the right direction tho! :slight_smile: