Help with orbit origin positioning

Hello, i’m making an orbitter script that works by slicing a circle by any amounts (like number of parts), then orbiting it by offsetting the starting point on the circle, it works perfectly

but when it comes to make the orbit fixed to the base’s orientation, it works but the orbit’s center position would be offsetted from the base pos

Here are the screen recordings

As you can see, the orientationing works, but it offsets the base

Here’s my code

local module = {}
local RUN = game:GetService("RunService")

export type OrbitConfigs = {
	PosCount:number?;
	Base:CFrame;
	Parts:{BasePart}?;
	Radius:number?;
	Offset:number?;
	Speed:number?;
	PositionSine:boolean?;
	SineAmp:number?;
	SineDuration:number?;
	SineAxis:Vector3?;
	AutoSineOffset:boolean?;
}

function getSineOffset(t, Amp, Mag, Axis)
	return Axis * Amp * math.sin(t * math.pi / Mag)
end

-- offset is from 0 - 1, or degrees, not required
function module:MakeCircle(num:number, base:Vector3?, radius:number?, offset:number?): {Vector3 | CFrame}
	offset = offset or 0
	local toReturn = {}
	local absolutePositions = {}
	for i = 1, num do
		local angle = (i + offset) * 2 * (math.pi / num)
		local absoluteCirclePos = Vector3.new(math.sin(angle), 0, math.cos(angle))
		local positionOnCircle = absoluteCirclePos * radius
		table.insert(toReturn, (base or Vector3.zero) + positionOnCircle)
		table.insert(absolutePositions, absoluteCirclePos)
	end
	return toReturn, absolutePositions
end

function module:Orbit(configs:OrbitConfigs)
	local offset = configs.Offset or 0
	local currentOffset = offset
	local CFrames = nil
	local startTime = os.clock() -- for sining pos
	local loop = task.spawn(function()
		while true do
			local currentTime = os.clock() - startTime
			local parts = configs.Parts
			local speed = configs.Speed or 1
			local count = configs.PosCount or #parts or 1
			local radius = configs.Radius or 5
			local baseCF = configs.Base or CFrame.new()
			if typeof(baseCF) == "Instance" and baseCF:IsA("BasePart") then
				baseCF = baseCF.CFrame
			end
			currentOffset += speed / 60 -- updates the positions, makes it orbit
			local positions = module:MakeCircle(count, baseCF, radius, currentOffset) -- returns CFrames because i didn't use baseCF.Position
			if parts then -- if a table of parts are provided updates their position, otherwise positions are still accessible
				for i, pos in ipairs(positions) do
					local part = parts[i]
					if configs.PositionSine then
						local t = currentTime
						local axis = configs.SineAxis or Vector3.new(0, 1, 0)
						if configs.AutoSineOffset then
							if i % 2 == 0 then
								t = -t
							end
						end
						local sinePos = getSineOffset(t, configs.SineAmp or 3, configs.SineDuration or 2, axis)
						pos += sinePos -- apply sine
					end
					local CF = baseCF * pos -- this is where i stumble on my problem
					part.CFrame = CF
					positions[i] = CF
				end
			end
			CFrames = positions
			task.wait()
		end
	end)
	return {
		UpdateLoop = loop;
		Configs = configs;
		GetCFrames = function()
			return CFrames
		end,
	}
end

return module

I’ve been trying to get this correct but my knowledge is sort of limited (especially math), any help would be appreciated!

Here’s the testing place file:
orbitTest.rbxl (50.4 KB)

If you move the position of the part to 0,0,0 does it work as expected?

Yes, as shown in the second video, or the start in the first video

Sorry, I didn’t see that. Perhaps the VectorToWorldSpace method could be useful. if you did for example part2.Position = part1.CFrame:VectorToWorldSpace(Vector3.new(0,5,0)) then part2 would be moved to 5 studs above part1 relative to the orientation to part1. There is also a similar method ToObjectSpace for CFrames which could help.

There is also the inverse of these which are :VectorToObjectSpace and :ToObjectSpace

1 Like

Thank you so much, it’s working now

1 Like

Sorryfor bothering you, there’s another problem

Positioning works, but when i rotate the base with a perpendicular axis, it does like this

I modified the code around line 80 - 81 to this:

local WorldSpace = baseCF:VectorToWorldSpace(pos.Position)
local CF = CFrame.new(WorldSpace, baseCF.Position)
part.CFrame = CF

How do i do this?

Turns out i was stupid, i didn’t think hard enough :sob:

I forgot i made the MakeCircle function that also returns the offset values, and i used the added values instead of it, that’s why it was offsetting itself from Vector3.zero by 2 times

thanks for the help tho…!