This is just a nifty little function I whipped up using a bit of trig that I felt like sharing.
It takes a vector3 and returns a table of vector3s which represent points in a circle around it in a landscape orientation, Similar to the ways tokens spawn in bee swarm simulator.
Nothing too complicated
--arclength represents the distance between each point (as an arc)
--I recommend it be the size of the items plus a bit of leeway.
local function ComputeCircleCoords(StartVector3, amountofitems,Arclength)--> table of vector3s
local AngleBetweenInDegrees = 360/amountofitems
local AngleBetweenInRad = math.rad(AngleBetweenInDegrees)
local Radius = Arclength/AngleBetweenInRad +2
local tab = {}
local currentangle = 0 --radians
for num = 1, amountofitems do
currentangle += AngleBetweenInRad
local z = math.cos(currentangle)*Radius
local x = math.sin(currentangle)*Radius
local vector3 = StartVector3 + Vector3.new(x,0,z)
table.insert(tab,vector3)
end
return tab
end
How it works
Placing items in a circle around something consists of taking it’s location, a vector3, and calculating a set number of points the same distance around it, without changing the y axis (so all the points are at the same height).
In Trigonometry, there’s something called “The unit circle”, which is a circle who’s center is at (0,0) on a x-y plane, and has a radius of 1.
This is useful because there are a few properties of the unit circle which we can use.
The unit circle is on a plane, so it has 2 axises, but that’s fine since we need 2 axises to put things in a circle around something.
One property of the unit circle that we’ll be using is that it can be used to find the coordinates of points that lay on it, based on an angle measure. That is to say, if I start an angle with a ray at the positive X axis, have the vertex at the point (0,0), and a ray going through any place on the circle, I can find the coordinates of the place it intersects the circle. This is true for any point on the circle.
How we do that is as follows: If the circle has a radius of 1 and is placed at (0,0), the Cosine and Sine of any angle (given in radians), represents the X and Y coordinates of the point where that angle would intersect the circle if measured the way we do above.
X coordinate = Cos(anglemeasureinradians)
Y coordinate = Sin(anglemeasureinradians)
We all know that the total amount of degrees in a circle is 360. So if I divide 360 by the number of items we want, I can get how far away from each other in degrees they are from each other, and then find their individual angle measurements easily. Then, we can simply convert it to radians to use the property I stated above to find the exact position it would be at on a circle with a radius of one.
This gives the X and Y coordinates, but there’s 2 problems.
1: It starts at point 0,0, when In reality we’d most like be starting elsewhere, since we want it to be around the given vector3, and not around the origin.
2: We may want the circle to have a larger radius than 1, since that’s probably too small to fit the items we want to place.
Solving the first problem is easy. Just take the starting vector3 and add the x and y positions we obtain from our calculations as offsets to get them to the appropriate position away from the starting vector3 . Note: although they are X and Y on the graph of the unit circle, they actually represent the X and Z axises in roblox, since those axises lay flat on the ground.
The second problem is a bit more challenging, and requires another property of circles.
In a circle with a radius different than 1, the position of a point on it can be represented in the same way as the unit circle, cosine and sine of the angle it makes, except each element is multiplied by the radius of the circle.
You can think of the unit circle as being a circle with a scale (radius) of 1, and since we want the circle to be bigger/smaller than that, we have to scale up the coordinates we found according to the radius.
Rather than specifying the radius of the circle, it’s slightly more convenient to specify the arclength, since this is ultimately how far away each item is from each other, and then find a suitable radius that can support that.
You can find the length of an arc in any circle by taking its angle measure, in radians, and multiplying by the radius of the circle.
ArcLength = AngleMeasurementInRadians * Radius
We can reverse this property to find the radius of the circle given the arclength, and the angle measure (which we found earlier)
Radius = Arclength/AngleMeasurementInRadians
Now we have a suitable radius that puts each item at the given arclength away from each other. We can multiply the coordinates we found by this, and add THIS as an offset to the starting vector3 to find the final location of each part.
Hopefully this explains the concept behind the function. Sorry for the college essay lol.