Problem with rotating parts and math

Hey guys, I’m currently trying to make a script where parts have a spiral-like motion out of a given position and then max out rotating equidistant to each other, like this:

This doesn’t work bad, but the problem is I have the wait time needed for a proper equidistant circle hard - coded, when really I want it to be dynamic and based off of other variables, meaning it’s pixel perfect. Does anyone know how I can achieve this?

wait(2)

local center = Vector3.new(0, 0, 0)
local radiusIncrement = 2
local heightIncrement = 2
local speed = 0.5
local revolutionsPerSecond = 1
local maxRadius = radiusIncrement * 2.5
local maxTimeElapsed = (maxRadius / radiusIncrement) / speed  -- Calculate the time to reach max radius

print(maxTimeElapsed)

function TrackPart(Part)

	local timeElapsed = 0

	game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
		
		timeElapsed = timeElapsed + deltaTime * speed

		local currentRadius = radiusIncrement * math.min(maxRadius / radiusIncrement, timeElapsed)
		local currentHeight = heightIncrement * math.min(1.5, timeElapsed)

		local angle = 2 * math.pi * revolutionsPerSecond * timeElapsed

		local newX = center.X + currentRadius * math.cos(angle)
		local newY = center.Y + currentHeight
		local newZ = center.Z + currentRadius * math.sin(angle)

		Part.Position = Vector3.new(newX, newY, newZ)
	end)
end

for i = 1, 10 do
	
	local P = workspace.Part:Clone()
	
	P.Parent = workspace
	
	TrackPart(P)
	
	wait(0.19)
end

Anyone? :sweat_smile:‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

You should set up the math so they all use the same time value, but instead use an angle offset to be evenly distributed in the circle

local RunService = game:GetService("RunService")

local revolutionsPerSecond = 1
local SpawnDelay = 1
local EaseInTime = 2
local MaxRadius = 8
local MaxHeight = 3
local MinHeight = 1.5
local center = Vector3.zero

local Parts = {}
for i = 1, 10 do 
	local Part = workspace.Part:Clone()
	Part.Parent = workspace
	table.insert(Parts, Part)
end

local function TrackParts()
	local StartTime = os.clock()
	local PartsAmount = #Parts

	local Connection = RunService.Heartbeat:Connect(function() 

		local TimeElapsed = os.clock() - StartTime

		for i, Part in ipairs(Parts) do 
			local angle = (math.pi*2)*revolutionsPerSecond*TimeElapsed + (PartsAmount - i + 1)/PartsAmount*(math.pi*2)

			-- // (TimeElapsed - SpawnDelay*(i-1)) -- This is to make the parts fade in one after the other. The division (/EaseInTime) then turns it into an alpha value (0% to 100%)
			-- // SpawnDelay is the delay between the parts spawning. EaseInTime is how long to reach a transparency of 0
			-- // You can make make other alpha values using this (such as one for the radius, and one for transparency)
			local alpha = math.clamp((TimeElapsed - SpawnDelay*(i-1))/EaseInTime,0,1)

			local newX = center.X + MaxRadius*alpha*math.cos(angle)
			local newY = center.Y + MaxHeight*alpha + MinHeight
			local newZ = center.Z + MaxRadius*alpha*math.sin(angle)

			Part.Transparency = 1 - alpha
			Part.Position = Vector3.new(newX, newY, newZ)
		end
	end)

	return Connection
end

TrackParts()

You might have to rework it to keep the same variables you used in the code you provided

1 Like

Thank you so much! I was stumped on this for hours :slight_smile:

1 Like

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