I’m making a grid system that generates in a cone but I need help I cant seem to get the parts to be exactly the same spacing on on directions
(also if there is a better way of doing this let me know)
here’s the code:
local numberOfRings = 6
local partSize = 1
local spacing = 5
local centerPosition = workspace.TestPart.Position
local coneAngle = math.rad(60)
local function calculatePartsPerRing(ring)
return math.floor(0.7 * ring^2 + 0.3 * ring + 4)
end
local function generateConeGrid()
for ring = 1, numberOfRings do
local partsPerRing = calculatePartsPerRing(ring)
local currentRadius = ring * spacing
local angleIncrement = coneAngle / (partsPerRing - 1)
local startAngle = -coneAngle / 2
for point = 1, partsPerRing do
local angle = startAngle + (point - 1) * angleIncrement
local x = centerPosition.X + currentRadius / 2 * math.cos(angle)
local z = centerPosition.Z + currentRadius * math.sin(angle)
local part = Instance.new("Part")
part.Size = Vector3.new(partSize, partSize, partSize)
part.Position = Vector3.new(x, 0, z)
part.Anchored = true
part.Parent = workspace
end
end
end
generateConeGrid()
The calculatePartsPerRing function is the critical part of the code here. I’ve rewritten it, however keep in mind that since we’re generating integers for the number of parts per “ring”, the spacing between parts in each ring will be consistent, however this distance may vary slightly within each ring. Let me know if this is sufficient for your use case.
local NUM_RINGS: number = 6 --The number of arcs to generate
local SPACE_BETWEEN_RINGS: number = 4 --The distance between each arc
local SPACE_BETWEEN_PARTS: number = 4 --The distance between parts within an arc
local CONE_CENTER: CFrame = CFrame.new(0,0,0) --The center of the "cone". CFrame type is recommended so both position and rotation can be adjusted
local CONE_RADIUS: number = 60 --Radius of the "cone" (in degrees)
local PART_SIZE: Vector3 = Vector3.new(1,1,1)
local function calculatePartsPerRing(ringRadius: number, angle: number, partSpacing: number): number
local ringCirc: number = 2 * ringRadius * math.pi --Circumference of the ring
local ringPerc: number = angle / 360 --Percent of the circumference that the ring includes
return math.floor((ringPerc * ringCirc) / partSpacing)
end
local function generateConeGrid(center: CFrame, angle: number, numRings: number, ringSpacing: number, partSpacing: number)
for ringNum: number = 1, numRings do
local ringRadius: number = ringNum * ringSpacing
local numParts: number = calculatePartsPerRing(ringRadius, angle, partSpacing)
local angleInc: number = math.rad(angle / numParts) --This is the angle between each part within an arc (in radians)
local angleOffset: number = (numParts / 2) + 0.5 --This number is used to offset the `partNum` variable in the loop below so arcs are centered relative to the `center` CFrame
for partNum: number = 1, numParts do
local theta: number = angleInc * (partNum - angleOffset) --Angle (in radians) to generate a part at
--If the parts rotation needs to match the rotation of `center`, use this method:
local offsetCFrame: CFrame = CFrame.new(
ringRadius * math.cos(theta),
0,
ringRadius * math.sin(theta)
)
--If rotation of the parts in unimportant, this may be a more intuitive method:
--local offsetCFrame: CFrame = CFrame.fromAxisAngle(Vector3.yAxis, theta) * CFrame.new(0,0,-ringRadius)
local part: Part = Instance.new("Part")
part.Anchored = true
part.CFrame = center * offsetCFrame
part.Size = PART_SIZE
part.Parent = workspace
end
end
end
generateConeGrid(
CONE_CENTER,
CONE_RADIUS,
NUM_RINGS,
SPACE_BETWEEN_RINGS,
SPACE_BETWEEN_PARTS
)
If there’s a different formula you want the “number of parts per ring” to follow then yeah, you can absolutely do that. The question is whether you want to maintain equally spaced parts within each ring or the angle they generate (you can’t keep both of these unless the distance between each ring is altered).
Oh i see, I changed some of the code but I need help with one more thing. (Im using this code for a pet system) how would i make it so the parts are evenly spread out if there isn’t the exact numParts per ring here is an example of what i mean
local NUM_RINGS: number = 4
local SPACE_BETWEEN_RINGS: number = 8
local SPACE_BETWEEN_PARTS: number = 9
local CONE_CENTER: CFrame = Knit.Player.Character.HumanoidRootPart.CFrame or Knit.Player.CharacterAdded:Wait().HumanoidRootPart.CFrame
local CONE_RADIUS: number = 125
local PART_SIZE: Vector3 = Vector3.new(1, 1, 1)
local function calculatePartsPerRing(ringRadius: number, angle: number, partSpacing: number): number
local ringCirc: number = 2 * math.pi * ringRadius
local ringPerc: number = angle / 360
return math.floor((ringPerc * ringCirc) / partSpacing)
end
local function calculatePartsPerRing2(ring)
return math.floor(0.7 * ring^2 + 0.3 * ring + 4)
end
local data = {}
local function generateConeGrid(center: CFrame, angle: number, numRings: number, ringSpacing: number, partSpacing: number)
for ringNum: number = 1, numRings do
local ringRadius: number = ringNum * ringSpacing
local numParts: number = calculatePartsPerRing2(ringNum)
local angleInc: number = math.rad(angle / numParts)
local angleOffset: number = (numParts / 2) + 0.5
for partNum: number = 1, numParts do
local theta: number = angleInc * (partNum - angleOffset)
local offsetCFrame: CFrame = CFrame.new(
ringRadius * math.sin(theta),
0,
ringRadius * math.cos(theta)
)
local part: Part = script["Cat Sunglasses"]:Clone()
part.Anchored = true
part.Parent = workspace
table.insert(data, {
part,
offsetCFrame
})
end
end
end
generateConeGrid(
CONE_CENTER,
CONE_RADIUS,
NUM_RINGS,
SPACE_BETWEEN_RINGS,
SPACE_BETWEEN_PARTS
)
RunServiceController.RenderStepped("RenderTesting", function(DeltaTime)
CONE_CENTER = Knit.Player.Character.HumanoidRootPart.CFrame or Knit.Player.CharacterAdded:Wait().HumanoidRootPart.CFrame
for index, _data in pairs(data) do
local part: Part = _data[1]
local cframe: CFrame = _data[2]
local partPosition = (CONE_CENTER * CFrame.new(0, 0, 2) * cframe).Position
part.CFrame = CFrame.lookAt(partPosition, Vector3.new(CONE_CENTER.Position.X, CONE_CENTER.Y, CONE_CENTER.Position.Z) + CONE_CENTER.LookVector * 5) * CFrame.Angles(0, math.rad(-90), 0)
end
end)