Help adding randomness to ray for hitscan gun

I’ve made a hitscan gun using rays. It all works fine I really just need help adjusting the following code to add some random spread to the bullets:

local function getWorldMousePosition()
    local mouseLocation = UIS:GetMouseLocation()
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
    
    result = workspace:Raycast(screenToWorldRay.Origin, directionVector, raycastParams)
    return result
end

I just want to add a few degrees of randomness to the ray direction, but I’m not sure how. I know I just need to adjust the directionVector, but any way I try to change it breaks my script so I’m asking for help here. Also I was able to get some spread by adding a random vector 3 to the directionVector but the spread was in a square which I think makes it seem wrong and all around I think that was a bad method

Do the same thing you did but this time save your past magnitude then normalize it after you add it then multiply that by your past magnitude

What do you mean by ‘normalize it after you add it’
I multiplied it by the previous magnitude, but I’m not sure what that part means. I’m not ultra great at working with rays yet and still don’t fully understand them sorry.

local function getWorldMousePosition()
	local mouseLocation = UIS:GetMouseLocation()
	local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
	local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
	local dirMag = directionVector.Magnitude
	local randomSpread = Vector3.new(math.random(-10,10),math.random(-10,10),math.random(-10,10))
	
	result = workspace:Raycast(screenToWorldRay.Origin, (directionVector + randomSpread)*dirMag, raycastParams)
	return result
end

result = workspace:Raycast(screenToWorldRay.Origin, (directionVector + randomSpread).Unit * dirMag, raycastParams)

hmmm it still seems to be spreading in a very square shape

Maybe this post can help you

Got it working thanks

------The function you gave me from the other post
-- axis: center line of cone
-- angle: angle from center to edge of cone
-- returns: a random unit vector inside the cone, evenly distributed along the partial surface of a unit sphere.
local function RandomCone(axis: Vector3, angle: number)
	local cosAngle = math.cos(angle)
	local z = 1 - math.random()*(1 - cosAngle)
	local phi = math.random()*math.pi*2
	local r = math.sqrt(1 - z*z)
	local x = r * math.cos(phi)
	local y = r * math.sin(phi)
	local vec = Vector3.new(x, y, z)
	if axis.Z > 0.9999 then
		return vec
	elseif axis.Z < -0.9999 then
		return -vec
	end
	local orth = Vector3.zAxis:Cross(axis)
	local rot = math.acos(axis:Dot(Vector3.zAxis))
	return CFrame.fromAxisAngle(orth, rot) * vec
end

--my updated function
local function getWorldMousePosition()
	local mouseLocation = UIS:GetMouseLocation()
	local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
	local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
	local dirMag = directionVector.Magnitude
	
	local newCF = CFrame.lookAt(screenToWorldRay.Direction,directionVector).LookVector
	local cone = RandomCone(newCF, .015)

	result = workspace:Raycast(screenToWorldRay.Origin, cone.Unit*dirMag, raycastParams)
	return result
end

Implementing the function from the other code took a lot of messing with for me because I had no idea what I was doing but this updated function seems to do exactly what I wanted, so I will be considering this solved, though I still don’t know if I’m doing it as effeciently as possible thanks. I’m just sharing so someone may find it useful in the future.

Could simplify it a little:

local function getWorldMousePosition()
	local mouseLocation = UIS:GetMouseLocation()
	local ray = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
	local cone = RandomCone(ray.Direction, .015)
	return workspace:Raycast(ray.Origin, cone * MAX_MOUSE_DISTANCE, raycastParams)
end
1 Like