Grid spacing help

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()

this is what it currently looks like

Can you clarify exactly what you’d like the outcome to be? Do you want the space between each part in an arc to be equal?

Yes I want the spacing in between each part the same but still in the arc shape

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
)
1 Like

Working on a solution, hoping someone will beat me to it.

image

Is there anyway I can still keep the same pattern for parts per ring?

Ring 1 - 5 parts
Ring 2 - 7 parts
Ring 3 - 11 parts
etc.

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

This is how it currently looks

Here is how I want it to look

Here is the code im using to test

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)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.