How do i make a part that orbits/rotates around another part?

Hello!

How could i achieve this in the most optimized way possible? Because there is going to be alot of parts that will rotate around another one.

Thanks!

2 Likes

If you offset the pivot of the object you’re rotating by the radius of rotation you want,
All you’d need to do is loop moving the Cframe.

part.CFrame = part.CFrame * CFrame.Angles(0, math.rad(1), 0)

You could tween it to make it smoother

2 Likes

The most simple idea probably similar to duct tape could use Weld and spin the center PrimaryPart or the Root part. (Though using math to do it would be better)

2 Likes

You can use a table to store the parts and iterate through them in the while true loop. Here’s an example script:

-- Place this script inside the center part

local orbitSpeed = 1 -- Adjust the value to change the speed of the orbit

local parts = {} -- Table to store the parts to be orbited

-- Add the parts you want to orbit to the table
table.insert(parts, workspace.Part1)
table.insert(parts, workspace.Part2)
-- Add more parts as needed

while true do
    for _, part in ipairs(parts) do
        local rotationAxis = (part.Position - script.Parent.Position).unit
        local angularVelocity = part:FindFirstChildOfClass("BodyAngularVelocity")

        if not angularVelocity then
            angularVelocity = Instance.new("BodyAngularVelocity")
            angularVelocity.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
            angularVelocity.Parent = part
        end

        angularVelocity.AngularVelocity = rotationAxis * orbitSpeed
    end

    wait()
end

Inside the while true loop, the script iterates through each part in the parts table using a for loop. It calculates the rotation axis between the part and the center part and applies a BodyAngularVelocity to rotate the part around the center part. If a BodyAngularVelocity component does not exist for the part, it creates a new one and sets its MaxTorque property to prevent any constraints on rotation.

1 Like

your first thing you posted works, only thing is that its vertical and not horizontal. I tried to fix the problem by rotating the part and adjusting variables but it doesnt work

1 Like

That’d be because you’re moving the part relative to the workspace, not the part itself.

I edited my response because looping a rotation with an offset pivot would be much more optimised - I’d advise trying this instead.

your new thing makes it spin on itself, i want to spin around another part

how can i change that? Is there a property?

1 Like
-- Get the parts you want to rotate
local rotatingParts = game.Workspace:WaitForChild("RotatingParts"):GetChildren()

-- Define the rotation speed
local rotationSpeed = 1 -- Adjust as needed

-- Function to rotate parts
local function rotateParts()
    for _, part in ipairs(rotatingParts) do
        -- Rotate the part around its Y axis
        part.CFrame = part.CFrame * CFrame.Angles(0, math.rad(rotationSpeed), 0)
    end
end

-- Run the rotateParts function in a loop
while true do
    rotateParts()
    wait() -- Wait for the next frame
end
  • Replace "RotatingParts" with the name of the parent object that contains all the parts you want to rotate.
  • Adjust rotationSpeed to control how fast the parts rotate.
  • The rotateParts function rotates each part around its Y-axis by the specified rotation speed.
  • The script runs in a loop, continuously rotating the parts without unnecessary overhead.

Remember to place this script in a LocalScript object if you want it to run on the client side or a Script object if you want it to run on the server side. Additionally, ensure that the parts you want to rotate are accessible from the script’s context (e.g., they are descendants of game.Workspace).

1 Like

thats great, but how do i make it rotate around another part? For exemple, a planet orbiting around the sun.

Set up your parts at the desired distance you would like them to orbit from.


Take the position of the middle part.
Group the orbiting part.
Paste the position of the middle part into the WorldPivot position of the orbiting part.

  1. Calculate Orbit Position: Determine the position of the rotating part relative to the center of rotation (the other part). You can use trigonometry to calculate this position based on the desired orbit radius and angle.
  2. Update Position: Continuously update the position of the rotating part based on the calculated orbit position. You can achieve this in a loop, updating the position over time to create the effect of rotation.

By adjusting the orbit radius, speed, and updating the position accordingly, you can make one part rotate around another part in Roblox Studio.

With your sun and planet example we could modify the script:

-- Get the parts for the sun and the planet
local sun = game.Workspace:WaitForChild("Sun")
local planet = game.Workspace:WaitForChild("Planet")

-- Define the orbit parameters
local orbitRadius = 10 -- Adjust the radius of the orbit
local orbitSpeed = 1 -- Adjust the speed of orbit

-- Function to update the planet's position in orbit
local function updateOrbit()
    -- Calculate the new position of the planet in orbit
    local angle = math.rad(orbitSpeed)
    local newX = sun.Position.X + orbitRadius * math.cos(angle)
    local newZ = sun.Position.Z + orbitRadius * math.sin(angle)
    local newPosition = Vector3.new(newX, planet.Position.Y, newZ)

    -- Update the planet's position
    planet.Position = newPosition
end

-- Run the updateOrbit function in a loop
while true do
    updateOrbit()
    wait() -- Wait for the next frame
end
  • Adjust orbitRadius to set the distance between the sun and the orbiting planet.
  • Adjust orbitSpeed to control how fast the planet orbits around the sun.
  • The updateOrbit function calculates the new position of the planet in its orbit based on the current angle and updates its position accordingly.
  • The script continuously updates the planet’s position in a loop, creating the effect of orbiting around the sun.

Make sure to place this script in a LocalScript or Script object depending on whether you want it to run on the client or server side. Additionally, ensure that the sun and planet parts are accessible from the script’s context.

1 Like

Alternatively, because you already said that it worked, you could just use the first script I sent. (which calculates with maths)

local RunService = game:GetService("RunService")

local function updatePosition(deltaTime)
    local angle = orbitSpeed * deltaTime
    local orbitPosition = centralPart.Position + Vector3.new(orbitRadius * math.cos(angle), orbitRadius * math.sin(angle), 0)
    orbitingPart.CFrame = CFrame.new(orbitPosition) * CFrame.Angles(0, 0, angle)
end

RunService.Stepped:Connect(function(deltaTime)
    updatePosition(deltaTime)
end)

Ohhhh the world pivot thing explains it all! This should work. Thanks!

No problem! Glad I could help.

i have one problem tho. I decided to ungroup the model and manually change the part’s pivot to my central part, but my problem is that i cant figure out how to rotate the part whilst keeping that pivot. Once i tried simply using CFrame.Angles(0, math.rad(), 0) it just would rotate on itself. I need to find a way to rotate it using position instead. Is that possible?

i tried this, and it works well, but is it possible for the part to look where its going? kinda like if, for exemple, someone was turning, they would look where they are going.

Go for my other solution then:

local RunService = game:GetService("RunService")

local function updatePosition(deltaTime)
    local angle = orbitSpeed * deltaTime
    local orbitPosition = centralPart.Position + Vector3.new(orbitRadius * math.cos(angle), orbitRadius * math.sin(angle), 0)
    orbitingPart.CFrame = CFrame.new(orbitPosition) * CFrame.Angles(0, 0, angle)
end

RunService.Stepped:Connect(function(deltaTime)
    updatePosition(deltaTime)
end)

If you have issues with that, do let us know!

local part = -- your part
local desiredRotationX = math.rad(90) -- rotate 90 degrees on the X axis
local newRotation = CFrame.Angles(desiredRotationX, 0, 0)
local combinedCFrame = part.CFrame * newRotation
part.CFrame = combinedCFrame

will rotate the part 90 degrees on the X-axis while keeping its original position. You can adjust it too if u want