Pretty much I want to raycast many directions from a position basically spreading out to cover as much area as possible. I want to be able to have a number of raycasts. E.g 10 or 5 and it will spread them out as much as possible. I’m mainly having trouble getting the directions. How should I go about doing this? Any help is greatly appreciated.
What is the application for this, so we can come up with the best solution?
If you know the exact number and its small, you could just hardcode some sensible directions.
Or you could use something like a fibonacci spiral distribution, like shown in this video from 1:44 to like 6:12: Coding Adventure: Boids - YouTube
I’m making a projectile in my game. Once it hits a surface I want it to spread out into smaller projectiles in every direction around it.
Watching the video helps me understand a little bit better. I’m still not sure how I would apply this to my own code however.
Here’s an implementation I found on stackoverflow that I ported to lua:
Edit for future readers: see the updated version of this below
My port:
local function EvenlyDistributeVectors(n)
if n == 0 then return {} end
if n == 1 then return { Vector3.yAxis } end
local vecs = table.create(n)
local phi = math.pi * (3 - math.sqrt(5))
for i = 0, n - 1 do
local y = 1 - (i / (n - 1)) * 2
local radius = math.sqrt(1 - y * y)
local theta = phi * i
vecs[i+1] = Vector3.new(
math.cos(theta) * radius,
y,
math.sin(theta) * radius
)
end
return vecs
end
That returns an array of vectors evenly distributed on a unit sphere.
You might also be interested in generating a random vector inside of a given cone:
this is what i tried, and it looks like it worked perfectly.
local cf = script.Parent.CFrame
for i = 1,360/10 do
local ray = workspace:Raycast(script.Parent.Position,cf * CFrame.new(Vector3.new(5,30,0)).Position - script.Parent.Position)
print(ray.Position)
local ins = Instance.new("Part")
ins.Size = Vector3.new(1,1,1)
ins.Position = ray.Position
ins.Anchored = true
ins.CanCollide = false
ins.CanQuery = false
ins.Parent = workspace
cf *= CFrame.fromOrientation(0,i,0)
end
this is the result:
this is a ray that is cast from the ground so i made the direction’s Y axis positive. i see that you want rays that spread outwards from the centre object so you can make the Y axis 0.
forgot to add a note: this only creates a 2D circle and not a 3D sphere like the one you want. to achieve casting rays in every direction, you can use this code and repeat it a number of times with an offset to the ray Direction.
Gonna try these out. Will update you on how it goes. I appreciate the help a lot!
Works perfectly! Thank you so much I’ve been struggling with this for a while.
Is there anyway to get specific points in the cone rather than a random point. Similar to the circle raycasts but with the cone.
Can you give an example of what you mean? And which of the two options are you using?
I used the raycast in every direction in a circle for something in my game. I also want to do something similar except I want the projectiles to be in a cone or half-circle almost shooting away from the player instead of in every direction. Like this:
The black dot being the player and the red lines being the rays in the cone. I want to be able to input a number similar to the circle and get multiple directions within that cone.
The difference between the cone raycasting you sent me and the version I want is that the one you sent gets a random direction. I want to be able to get multiple directions evenly spread out in the cone if that makes sense.
This should work for you. You’ll have to rotate the generated vectors, because this just assumes you want the cone pointed in the “world -Z axis direction”. That should make it easy because you can e.g. do part.CFrame * vec
on each vector to point the cone in the same direction as part.LookVector
.
That or you can take the last half of the RandomCone
method above to rotate them inside the function.
-- generates vectors in a cone whose axis is the -Z axis
-- n: number of vectors to generate
-- angle: angle between the -Z axis and the edge of the cone
local function EvenlyDistributeVectorsInCone(n, angle)
if n == 0 then return {} end
if n == 1 then return { -Vector3.zAxis } end
local cosAngle = math.cos(angle)
local vecs = table.create(n)
local phi = math.pi * (3 - math.sqrt(5))
for i = 0, n - 1 do
local a = i / (n - 1)
local z = -1 + (1-cosAngle)*a
local radius = math.sqrt(1 - z * z)
local theta = phi * i
vecs[i+1] = Vector3.new(
math.cos(theta) * radius,
math.sin(theta) * radius,
z
)
end
return vecs
end
Will try this when I get the chance! Thank you so much for all the help!
How exactly do I apply the directions? Here is my code:
My cone function (I took the bottom half from the random cone like u suggested)
local function EvenlyDistributeVectorsInCone(n, angle, axis)
if n == 0 then return {} end
if n == 1 then return { -Vector3.zAxis } end
local cosAngle = math.cos(angle)
local vecs = table.create(n)
local phi = math.pi * (3 - math.sqrt(5))
for i = 0, n - 1 do
local a = i / (n - 1)
local z = -1 + (1-cosAngle)*a
local radius = math.sqrt(1 - z * z)
local theta = phi * i
local vec = Vector3.new(math.cos(theta) * radius,math.sin(theta) * radius,z)
local cancel = false
if axis.Z > 0.9999 then
cancel = true
elseif axis.Z < -0.9999 then
vec = -vec
end
if cancel == false then
local orth = Vector3.zAxis:Cross(axis)
local rot = math.acos(axis:Dot(Vector3.zAxis))
vec = CFrame.fromAxisAngle(orth, rot) * vec
end
vecs[i+1] = vec
end
return vecs
end
the axis is the humanoidrootpart lookvector but for some reason it considers the cone always to the right of my character. Why is this and how can I fix it?
and heres the code where I use it
local firecount = 5
local directions = EvenlyDistributeVectorsInCone(firecount,5,char.HumanoidRootPart.CFrame.lookVector)
for i = 1,firecount do
local direction2 = directions[i]
local rc = raycastfire(char,char["Left Arm"].Position - char["Left Arm"].CFrame.upVector*0.5,direction2*10,raycastParams2,blacklisttable2)
if rc ~= nil then
SSS.events.ApplyEffect:Fire(rc.Instance,"PlaceFire",{rc.Position,rc.Normal})
end
end
Really good attempt, there’s just a few tweaks to some negatives and things you needed. I also cleaned up the if statement stuff but your method also would work.
local function EvenlyDistributeVectorsInCone(n, angle, axis)
if n == 0 then return {} end
if n == 1 then return { axis } end
local cosAngle = math.cos(angle)
local vecs = table.create(n)
local phi = math.pi * (3 - math.sqrt(5))
for i = 0, n - 1 do
local a = i / (n - 1)
local z = -1 + (1-cosAngle)*a
local radius = math.sqrt(1 - z * z)
local theta = phi * i
local vec = Vector3.new(math.cos(theta) * radius,math.sin(theta) * radius,z)
if axis.Z > 0.9999 then
vecs[i+1] = -vec
continue
elseif axis.Z < -0.9999 then
vecs[i+1] = vec
continue
end
local orth = -Vector3.zAxis:Cross(axis)
local rot = math.acos(axis:Dot(-Vector3.zAxis))
vec = CFrame.fromAxisAngle(orth, rot) * vec
vecs[i+1] = vec
end
return vecs
end