Been stuck for hours on fixing my orbiting system

So recently I have been researching and trying to script a planet which revolves around the sun, using the gravity formula:
F = G(m1m2)/R2

Everything has been scripted as I thought it should be, however it shows no evidence that it’s orbiting, but rather the planet crashing into it.

I tried numerous google searches with no answers and I tried setting the initial velocity, which I don’t know If I did it right, but I can’t get it to work. So I really appreciate some help.

Update: As this discussion was going, I tried playing around and it all seems to either go linear (due to planets gravitational force) or right in the sun due to low intiialvelocity and no other planets involved.

Now the main problem I’m facing is figuring out how I should set the initial velocity.

Video, Code, Explorer tab below:

Main script:

local universe = require(game.ServerScriptService.Universe)

game:GetService("RunService").Stepped:Connect(function()
	for i,Body in pairs(workspace.Objects:GetChildren()) do
		local surfaceGravity = Body.SurfaceGravity.Value
		local radius = Body.Radius.Value
		local mass = surfaceGravity * radius * radius / universe.grav
		Body.mass.Value = mass
	end
end)


local run = 0

game:GetService("RunService").Stepped:Connect(function()
	
	for i,thisBody in pairs(workspace.Objects:GetChildren()) do
		for i,otherBody in pairs(workspace.Objects:GetChildren()) do
			if otherBody~=thisBody then
				local sqrdist = math.sqrt((otherBody.Position - thisBody.Position).Magnitude)
				local forceDir = (otherBody.Position - thisBody.Position)
				local NormalizedVector = forceDir.Unit
				
				local force = NormalizedVector * universe.grav * 
					thisBody.mass.Value * otherBody.mass.Value / sqrdist;
				
				local acceleration = force/thisBody.mass.Value
				local currentvelocity = acceleration * universe.dt
				
				if thisBody.Name == "Planet" then --and run==0 then
					currentvelocity += thisBody.InitialVelocity.Value
					print(currentvelocity)
				end
				
				--thisBody.LinearVelocity.VectorVelocity += currentvelocity * constants.dt
				thisBody.Position += currentvelocity * universe.dt
				
			end
		end
	end
	
	run += 1
end)

Module script

local module = {}

module.grav = 0.0001
module.dt = 0.01

return module

image

image

Note: If a place file is needed, let me know.

================================================================

THIS POST HAS BEEN SOLVED:
With the solution provided, planets and stars are able to orbit with ease. (also I used linearvelocity)


1 Like

What’s the planet’s initial velocity? If it’s 0 relative to it’s orbiting body, then yeah it’s going to just fall it. It needs some velocity in the plane perpendicular to the direction to the orbiting body to “miss” the orbiting body.

1 Like

It was 0,0,-1000.

I started to realize that -1000 is too small to notice since the size of the sun is ten times bigger, so just now I tried setting it to -10000, but instead of orbiting. It slowly goes in a straight line, escaping the orbit completely.

I know that it’s because of this specific code, and all I did was adding the same starting velocity in every loop…

if thisBody.Name == "Planet" then --and run==0 then
	currentvelocity += thisBody.InitialVelocity.Value
	print(currentvelocity)
end

The main problem is that I don’t know how to set the initialvelocity the right way.

1 Like

Seems your code might be working. If the initial velocity is high, the object would escape. If it is too low, it would crash.

It you are just having fun, why not try 10 moons at the same time, with different velocity.

If you want to have an orbit that can go on forever, maybe you will be better of with a hinge constraint with motor enabled, although as a gravity simulator that would be cheating. :slightly_smiling_face:

2 Likes

Just play around with it until you find a stable orbit. Try moving the planet closer (so the “high” initial velocity is closer to an orbital velocity at that distance), or try increasing the gravitational constant, or increase the mass of one or both bodies.

EDIT: Or you could compute the escape velocity and just pick any velocity less than that (but not 0)

Never use division like this, instead create a constant for it.

local UniverseConstant = 1 / universe.grav
for i,Body in pairs(workspace.Objects:GetChildren()) do
		local surfaceGravity = Body.SurfaceGravity.Value
		local radius = Body.Radius.Value
		local mass = surfaceGravity * radius * radius * UniverseConstant
		Body.mass.Value = mass
	end

Remember that division sucks and you should avoid it.
Second thing is that you are using body movers, you don’t need to.
Instead create your own “objects” aka tables in modules which will represent planets and you will describe their properties in those tables.
Example:

local function createObject()
     local object = {}  
     object.Position = Vector3.new()
     object.Radius = 5 --It's Size divided by 2 
     object.ReferenceInWorkspace = nil  
     return object 
end
--[[Remember that tables don't work like Vector3 or any roblox's special 
datatypes since you have not added any metamethods in, so whenever you 
change something inside of this table, you don't get them to duplicate.
So when you do something like this:
local tab = {}
local tab2 = tab
tab.a = 5
print(tab.a) -- 5
print(tab2.a) -- 5
You can see that those tables are the same references.
]]--

Instead of calculating sqrdist you could calculate it’s inverse since you are not using it in any other way anyways.
Here’s he formula: InverseSqrdDist = ((otherBody.Position - thisBody.Position).Magnitude)^(-(0.5))

0.5 used in power operator is a squareroot
minus near the power operator creates the inverse
if we combine those two things you get inverse of a square root which is the thing you want.
So instead of dividing by the square root you multiply by it’s inverse making your script much faster.

2 Likes

you give it some sideways velocity and it will orbit instead of crashing into the planet

i have done this before, and you just need perfect math to get it working

@solsort500 @ThanksRoBama

It’s getting weird now because a couple of results happen when I played around with it:

  • When lowering the initialvelocity, no matter how far or near it gets, it will always goes straight (due to initialvelocity) then bending its orbit curved to the sun. Thus not even a single orbit was made.
  • Adding multiple planets like four or ten of them, only goes in a straight line (or slightly bended to the sun as well) because of the surrounding planets

Also it has nothing to do with mass I suppose. Mass is set by script.
Increasing the gravitational constant leaves no effect whatsoever, same result.

I still have the feeling however that the code I had shown above is the problem.

Since I said what I wanted, now I can get to the problem solving. The solution is pretty simple, you calculate the gravity velocity, and then you switch the velocity axis, thank you for the attention.

Example → input x,y,z : output z * orbitspeed,x * orbitspeed,y*orbitspeed.
Or you basically switch the values so the biggest influence is swapped with the smallest once etc…

Yeah that’s what I’m trying to do right now, which I can’t do right now, so I need assistance.

I’m a little confused on this part, I don’t know how you would type it out.

also thanks for that scripting optimization and feedback

You basically swap x,y,z values.
It could potential create some funny orbits, but the idea behind this is you know that objects are attracted by the gravity so they collide, so what you do if you want them to orbit around themselves, you swap those axis values, so x is now z, y turns into x, and z becomes x and you get a potential desired orbit velocity.

Nope, it does the opposite of what we wanted lmao

z,x,y
z,y,x
Planets going the opposite direction in parallel, but going up

y,z,x
y,x,z
x,z,y
Planets going the opposite direction in parallel, but going down the void

Here is my script that i used a few months ago to achieve what you’re trying to do:

local G = 2.396 * 10^-10

for _, object1 in pairs(game.Workspace:GetChildren()) do
	for _, object2 in pairs(game.Workspace:GetChildren()) do
		if object1.ClassName == "Part" and object2.ClassName == "Part" then
			if object2.Name == "Sun" then
				if object1 == object2 then
					continue
				end

				local distance = (object1.Position - object2.Position).Magnitude

				local magnitude = G * object1.Mass * object2.Mass / distance

				local line_force = Instance.new("LineForce")
				local attachment1 = Instance.new("Attachment")
				attachment1.Parent = object1
				local attachment2 = Instance.new("Attachment")
				attachment2.Parent = object2

				line_force.Name = object1.Name.." To "..object2.Name
				line_force.ApplyAtCenterOfMass = true
				line_force.InverseSquareLaw = true
				line_force.ReactionForceEnabled = true
				line_force.Magnitude = magnitude * 950000000000
				line_force.Attachment0 = attachment1
				line_force.Attachment1 = attachment2
				line_force.Parent = game.Workspace
				local v = math.sqrt(G * object2.Mass / distance) * 60000
				object1.AssemblyLinearVelocity = Vector3.new(v, 0, 0)
			end
		end
	end
end

1 Like

in the last two lines you can see how i calculate velocity needed to push it into orbit

It doesn’t look to me like you’re tracking velocity between steps? That’s pretty critical. That’s why your objects are moving linearly instead of accelerating.

If you give an object velocity, it should constantly maintain that velocity every frame. When a force acts on the object, change the velocity rather than the position.

And when you set the initial velocity, only set it for the first frame.

I did try to set the initial velocity first frame (with the run method as a test) but it doesn’t seem to work…?

run = 0
runservice loop()
if is a planet then and run==0 then
   currentvelocity += intialvelocity 
end

run+=1
end)

I might have to try and test it again once I get back home but with more starting velocity

But it doesn’t look like you maintain velocity between frames. Gravity needs to be added to velocity rather than position, and you need to manually save the previous velocity in a table or Attribute.

It should look like this pseudo-code.

set initial velocity into a table or Attribute
loop or event
    get velocity from table or Attribute
    add gravity to velocity
    add other forces to velocity
    add velocity to part position in Workspace
    save velocity to a table or Attribute so it can be used next loop
end
1 Like

Funny, right this instant I’m working on a gravitation game too. I don’t use this method though, I use LineForces. It’s way simpler to let Roblox handle the physics, and it’s also less expensive, more efficient and easier to manage. Just a suggestion.

Too, you should know that earth, the moon, and the sun are EXTREMELY far away from each other. More than we think, so when trying to simulate it, yes it may look more boring, but we will get way better results if you put the objects farther away from each other. The farther away they are, the more stable the orbits are.

Also, you should know about the Three Body Problem.

Though you could achieve the same effect by decreasing gravity, mass, or time.