Help with orbital gravity script

Hello! I recently made an orbital gravity script, taking things from a YouTube video called Coding Adventure: Solar System and adapting the equasion to use in Roblox with VectorForces. It works fine, when there is one small planet and a huge star object, the planet gets sucked into the star. However, as soon as I add another object, bigger than the planet, the force in both objects don’t make them move due to it trying to attract to both objects I’m assuming. Can anyone help me fix this?

Images:
Works: image
Doesn’t work: image

Code:

local RunService = game:GetService("RunService")

local bodies = workspace.Bodies

function updateForce(body, otherBody)
	local bodyMass = body:GetMass()
	local otherBodyMass = otherBody:GetMass()
	
	local radius = body.CFrame.Position - otherBody.CFrame.Position
	local scalarForce = (bodyMass + otherBodyMass) / radius.Magnitude^2
	local force = radius.Unit * scalarForce
	
	body.GravityForce.Force = -force
	otherBody.GravityForce.Force = force 
end

for _, body in pairs(bodies:GetChildren()) do
	local gravityForce = Instance.new("VectorForce")
	local attachment = Instance.new("Attachment")
	
	attachment.Parent = body
	
	gravityForce.Name = "GravityForce"
	gravityForce.Attachment0 = attachment
	
	gravityForce.Parent = body
end

RunService.Stepped:Connect(function()
	for _, body in pairs(bodies:GetChildren()) do
		for i, otherBody in pairs(bodies:GetChildren()) do
			if otherBody ~= body then
				updateForce(body, otherBody)
			end
		end
	end
end)
2 Likes

Each body experiences one force due to the gravity of each other body. If a planet pulls the moon with some force, and the sun also pulls the moon with some force, the resulting force is the sun of those forces. That resulting force is what you need.

That means each body needs to look at every other body to figure out what the force needs to be.

That would look something like this:

function updateForce(body)
	local resultingForce = Vector3.new()
    for _, otherBody in pairs(bodies:GetChildren()) do
        if otherBody ~= body then
			local bodyMass = body:GetMass()
			local otherBodyMass = otherBody:GetMass()
			
			local radius = body.CFrame.Position - otherBody.CFrame.Position
			local scalarForce = (bodyMass + otherBodyMass) / radius.Magnitude^2
			local force = radius.Unit * scalarForce
			
			resultingForce = resultingForce + force
        end
    end

    --Don't need to set the GravityForce on the other body, because it also gets updated in the RenderStepped loop
    body.GravityForce.Force = -resultingForce
end


RunService.Stepped:Connect(function()
	for _, body in pairs(bodies:GetChildren()) do
		updateForce(body)
	end
end)
4 Likes

Thank you very much for the response and explanation!

1 Like

Happy to see someone else trying to do this kind of thing on Roblox as well. :slight_smile:

If you need help with more accurately simulating an orbiting objects position as a function of time I am currently working on a script that simulates one-body orbits using Kepler’s equations.

Script (old):
https://www.roblox.com/library/4829401641/Orbit-Kit

Place with current script (newest):
https://www.roblox.com/games/4888188585/Newtonia

Place with even older version of the script (but looks nicer):
https://www.roblox.com/games/3092114897/Project-Newton

3 Likes

Thank you very much! I’m really interested in space, physics etc so that’s why I decided to try doing this. Your resources might help me too!

1 Like