Line trace spread

I haven’t done anything with spread yet in c++ but i can do it in blueprint. So far i have made it so it goes in a diagonal line but im not sure how i can make it so its random in x.y.z

Sorry for the blury image tried capturing it in a gif



Personally, I would use…

FVector RightVector = Character->GetFirstPersonCameraComponent()->GetRightVector();
FVector UpVector = Character->GetFirstPersonCameraComponent()->GetUpVector();

… and treat them as a pitch and yaw axis to rotate your forward vector around.

To make it behave much more like a cone, you could constrain these pitch and yaw values by converting to them from 2D polar coordinates (angular deviation and rotation – think like Saturation and Hue, respectively, in UE4’s color picker). Pitch and yaw by itself would behave more like a rectangular pyramid with a bulge (basically, as if the color picker was square, not circular).

From there, you just need to decide how far along that vector the trace needs to go.

You need three random floats, spreadX, spreadY, and spreadZ.
Then you can add a FVector spread(SpreadX, SpreadY, SpreadZ).
You probably want to scale the spread value by the forward distance, too, else you’ll get more spread (in degrees) for shorter traces.)

Using UpVector and RightVector and adding random spreadUp and spreadRight times each of those is another good idea – more to type, but more predictable.

Or You can use functions from FMath:

 * Returns a random unit vector, uniformly distributed, within the specified cone
 * ConeHalfAngleRad is the half-angle of cone, in radians.  Returns a normalized vector. 
static CORE_API FVector VRandCone(FVector const& Dir, float ConeHalfAngleRad);

 * This is a version of VRandCone that handles "squished" cones, i.e. with different angle limits in the Y and Z axes.
 * Assumes world Y and Z, although this could be extended to handle arbitrary rotations.
static CORE_API FVector VRandCone(FVector const& Dir, float HorizontalConeHalfAngleRad, float VerticalConeHalfAngleRad);

Thanks for all your suggestions. I have tried jwatte’s suggestion and it works but i was wondering if you could tell me if i need to make the spread bigger, would this look realistic and have i made my code more complicated than it needs to be?

Here is a gif of it:

And this is my code how i have done it:


looks cool :slight_smile:

but as Pierdek said - use RandVectorInCone

It is built in to the engine and exposed in Blueprints too…

Why reinvent the wheel?

I don’t think it has been mentioned yet.
The way you have it set up now it’s possible to get “unlucky” under certain circumstances. Depending on the random SpreadCone vector components and InstantData.WeaponRange the EndTrace location may end up being left, right, above, below or even behind the StartTrace location (or somewhere between those extremes). And even if it is exactly in the direction of the ForwardTrace vector, your WeaponRange value will no longer be accurate since you ADD your random spread on top of that, no matter what.

Again the solution would be to use RandVectorInCone.

I was looking at that but it looks confusing and im not sure how i would set it up

Like i havent looked at Static CORE_API so i dont know what it means or does and i dont know if i need to change the const& dir or ConeHalfAngleRad

static CORE_API FVector VRandCone(FVector const& Dir, float ConeHalfAngleRad);
static CORE_API FVector VRandCone(FVector const& Dir, float HorizontalConeHalfAngleRad, float VerticalConeHalfAngleRad);

Jwatte’s suggestion had two fail-safes for this:

  1. Have the randomness to be some constant fraction of InstantData.WeaponRange.
  2. Take that vector, normalize it, then multiply it by InstantData.WeaponRange so you don’t get abnormally short or long traces.

Those are the Fmath declarations. You use them like this:

FVector ForwardVector = Character->GetFirstPersonCameraComponent()->GetForwardVector();
float SpreadHalfAngleRadians = FMath::DegreesToRadians(15.0)
FVector ConeVector = FMath::VRandCone(ForwardVector, SpreadHalfAngleRadians)

This example has a hardcoded spread cone half angle of 15 degrees.

Thanks for the examples i understand it now the documents are hard for me to understand :slight_smile:
This seems a lot easier now the other way i was doing it got really messy now its a lot clear.

Yeah, there’s a lot of good helper functions in UE4. Learned something from this thread, myself.

Indeed. But since neither of these have been taken into account in the code posted by rapiidzz901 I thought it would be better to point out again.

Yup. Personally, I would probably do my method (which converts from 2D polar coordinates to angular displacement from forward vector) over Jwatte’s or Epic’s. It’s not that long to program, and you can control the distribution (which is especially helpful if used for multiple, different weapons). I’m guessing Epic’s has equal probability anywhere in the cone, while Jwatte’s method is center-weighted by the volume distribution of an world-axis-aligned box (although it could be turned into a sphere easily enough) when projected into 2D. In my case, I could just have the 2D polar coordinates radius (distance from crosshair) be mapped to any non-linear driver. I could even force multiple traces in a burst (shotgun) to be spread out from one another, albeit otherwise random.

But yeah, for pure random rays in a cone, use Epic’s one-step utility method of course.

I am working on a similar problem and I having some issues with the Epic VRandCone function. Despite the comments and what the algorithm should be doing I am still seeing clumping/hotspot in the middle around the cone direction vector when I fire my rays. I tend to end up with very few on the outside extents of my cone. Given enough time/samples it starts to even out more but for my current setup it is a bit of a problem as I need a better distribution. I am starting to wonder if it is more of just a geometry problem so that even though the ray distribution is uniform I will still be getting something happening around the cone axis due to shallower angles?

I do know the plane these rays intersect on and could do a sort of rejection sampling and refetch a new random if there are too many rays per area on the intersection plane. Sorry for the rambling but I am a bit lost with this function.

Any thoughts?