How to make this ray local space and not world space?

Currently, I’m trying to solve a problem in my game.

Shooting at a wall has the intended effect for this demonstration, where the spread pattern is almost flat.

However, when aiming at the ground, it becomes a circular spread pattern. I need it so it’s almost flat no matter what angle you’re shooting.

Here is the ray variable:

		local ray =, (mouse.Hit.p - game.Players.LocalPlayer.Character.Head.Position).unit * settings.gunSettings.range + gunset.gunSettings:spreadPattern().unit*chosenSPREAD)

What it looks like when shooting at the wall and how I want it to look when shooting at the ground:

What it looks like shooting at the ground (not intended):

Here’s what SpreadPattern() is:

	spreadPattern = function()

You can define a spread look vector with an angle of n by doing:

local origin = game.Players.LocalPlayer.Character.Head.Position
local dir = (mouse.Hit.p - game.Players.LocalPlayer.Character.Head.Position).unit

local cf =,origin + dir) 
    * CFrame.Angles(0,0,math.random()*math.pi*2)
    * CFrame.Angles(n*(math.random()*2-1) ,0,0)

local lookVector = cf.LookVector
local range = settings.gunSettings.range
local ray =, lookVector*range)

You can probably replace n with chosenSPREAD and be fine. This snippet should give you a look vector in the direction you want it to go to, while adding a random spread with respect to max angle n.

Also, I’m assuming you want everything in between of -1 and 1 when getting the spread instead of just one or the other, so I suggest doing math.random()*2-1 instead of math.random(-1,1) when solving for a random number between -1 and 1.

1 Like

Which of these CFrame.Angles() would be the actual spread?

I’m assuming it’s the first one.

Should also be noted that the spread for all of the weapons are way more than they’re supposed to be:

n is in radians, not angles. If your input is angles you can just do math.rad(n)

The last CFrame has the value n in it, which makes it the CFrame that inflicts the spread. The second CFrame rotates it randomly around another axis that doesn’t interfere with spread. You don’t need to worry about that one.

1 Like

Thanks for that tidbit.

It’s now working as intended. :smiley:

Also, ChosenSpread is a number that is chosen in place of the spread variable, if it’s set to have variable spread.

Meaning, the longer you shoot, the bigger the spread becomes.

Is there a way to create a cooldown for this? Instead of it instantly going away as soon as let off the trigger.

Thank you for your help! :slight_smile:

No problem :smiley:

Instead of setting your spread back to 0 once you stop firing, you can decrease it slowly over time.

1 Like

What’s the best method for this?

I’ve considered using a repeat loop, but I don’t think that’s the most efficient.

That’s the biggest problem I’m facing right now, is I’m not sure what would be the best method for handling something like this.

1 Like

Would something like this not work?

local spread = 1

local function setSpread(amount, increment)
   for i = 1, amount, increment do
      spread = i

So calling setSpread(10, 0.1) would set the spread to 10 in increments of 0.1. Then tween/resize the GUI accordingly.

1 Like

Wouldn’t it constantly be fighting with the spread increasing / decreasing?

Because if you stop shooting, then fire again, you’re going to have one instance trying to increase it while the other is trying to decrease it, making it jump between the two repeatedly, at least, in my experience.

Put an if statement.

local spread = 1
local canSpread = true
local function setSpread(amount, increment)
   if canSpread == true then
      for i = 1, amount, increment do
         spread = i

Control canSpread however youd like. (Sorry I’m 3 hours late, had to do some stuff.

1 Like