# Problem with simple planet orbitting script

i used a planet orbitting script from a devfoum resources and editting to have eccentricty and orbital plane but there is a problem with my script which i dont know how to fix

The module script

``````local RunService = game:GetService("RunService")

local CosineMath = math.cos
local SineMath = math.sin
local Atan2Math = math.atan2

local PIMath = math.pi
local TAU = 2*PIMath
local TweenS = game:GetService('TweenService')
return function(PlanetOrbiting : PVInstance, PlanetGettingOrbited : PVInstance,Distance: number, TimeToOrbit : number, Eccentricity : number, OrbitalPlane : number)
assert(PlanetOrbiting ~= PlanetGettingOrbited, "Cannot orbit itself, PlanetOrbiting and PlanetGettingOrbited should be different")

local DifferenceVector = PlanetOrbiting:GetPivot().Position-PlanetGettingOrbited:GetPivot().Position --Differnce

local Angle = Atan2Math(DifferenceVector.Y, DifferenceVector.X)--Angle
local HeartbeatConnection
HeartbeatConnection = RunService.Heartbeat:Connect(function(DeltaTime)
-- Disconnect the event if one of the planets got destroyed
if not (PlanetOrbiting or PlanetGettingOrbited) then
HeartbeatConnection:Disconnect()
HeartbeatConnection = nil
end

-- Polar coordinates 2D
local x
local y
local z = 0
local offset
if Eccentricity < 0 then
x = (Distance+-Eccentricity)*CosineMath(Angle)
y = Distance*SineMath(Angle)
elseif Eccentricity == 0 then
x = (Distance)*CosineMath(Angle)
y = Distance*SineMath(Angle)
elseif Eccentricity > 0 then
x = (Distance+Eccentricity)*CosineMath(Angle)
y = Distance*SineMath(Angle)
end
PlanetOrbiting:PivotTo((CFrame.new(PlanetGettingOrbited.Position)*offset)*CFrame.new(x, y, z))
Angle += DeltaTime*TAU/TimeToOrbit
end)
--HeartbeatConnection:Disconnect()
-- Return the heartbeat connection, so we can disconnect it if we no longer wants the part to orbit
return HeartbeatConnection
end
``````

so if you put eccentricty as 15 it would look like this

But the thing with this is that the planet is moving at a constant speed but in real life planets move faster as they are closer to their parent object like this

this is how my code works in game
the speed is same on all places which isnt what i want

Any idea on how to create that?
Thanks!

1 Like

If you want real life behavior you should look at real life equations which account for acceleration and velocity. Seems like someone else has already done it:

Or you could just let the physics engine do it for you with a line force and such.

i mean i could but i really suck at math especially stuff like this complicated

2 Likes

you can use Magnitude to speed thing up

Do you only want the orbits to be realistic for 2-body systems? Or do you need it to also work with 3 or more bodies?

How tho ik magnitude gives me a distance between two points right?

1 Like

just two bro i want to create the most least complicated orbit system that has almost all the things that real orbit has

the eccentricty works but the speed is constant all times which should happen cuz the closer you the faster you go

1 Like

If you really want the simplest possible simulation, you can use numerical integration to simulate the system. This has the advantage that it works for any number of bodies, not just 2. In fact AFAIK itâ€™s the only approach that works for more than 2 bodies.

Each body is just a particle that follows Newtonâ€™s laws of motion, and where the acceleration on a particle is given by Newtonâ€™s law of gravitation.

The specific equations we need are

`a = F / m`

`ds = dv * dt`, `s` being the position of a body and `dt` being the change in time (the â€śtime stepâ€ť).

`dv = a * dt`

and

`F = G * (m1 * m2) / r^2`, `G` being the gravitational constant.

How the simulation works is explained here:

Basically, you simulate the system in small time steps. Each step, you change the position of each body by itâ€™s speed * dt, you change the velocity by acceleration * dt, and you set the acceleration on a body to be the sum of forces on that body due to gravity from the other bodies.

In code, that looks like so:

``````local G = 1 --tune this to get a simulation that "feels right".

local bodies = {}

function newBody(mass: number, p0: Vector3, v0: Vector3)
local body = { mass = mass, position = p0, velocity = v0 }
table.insert(bodies, body)
return body
end

function getBodyGravitationForce(body): Vector3
local forceSum = Vector3.new()
for _, body2 in ipairs(bodies) do
if body2 == body then continue end --Bodies don't attract themselves. Also distance would be NaN, breaking everything.
--Newton's law of universal gravitation
local distance = (body.position - body2.position).Magnitude
forceSum += G * body.mass * body2.mass / (distance * distance)
end
return forceSum
end

function stepSimulation(dt)
--Calculate new positions and velocities for each body
local newPositions = {}
local newVelocities = {}
for _, b in ipairs(bodies) do
--Newton's laws of motion
local acceleration = getBodyGravitationForce(b) / b.mass
newVelocities[b] = b.velocity + acceleration * dt
newPositions[b] = b.position + b.velocity * dt
end

--Apply new positions and velocities
--This is done *after* simulating *all* bodies.
--Otherwise changes to one body would affect calculations for the bodies that come after
for _, b in ipairs(bodies) do
b.velocity = newVelocities[b]
b.position = newPositions[b]
end
end

local v3 = Vector3.new

newBody(10, v3(0,  0, 0), v3(0, 0, 0))
newBody(1,  v3(10, 0, 0), v3(0, 0, 8))

game:GetService("RunService").Stepped:Connect(stepSimulation)
``````

I havenâ€™t tested this so there might be some bugs or typos, but the overall idea works.

This way has some disadvantages if you just want 2 bodies. First, if you want to know the position of particles at some point in time then have to simulate all the way to that point in time. Second, real life motion is continuous and not discrete (it doesnâ€™t move forward in steps). This causes some inaccuracy in the simulation which accumulates over time, meaning youâ€™ll get wildly inaccurate results after a while. The smaller the time step the better the simulation. If you want smaller time steps without making the sim run slower, you can step it forwards e.g. 10 times every Stepped, but only do it by dt / 10 each step. Of course at some point the CPU will be unable to keep up so thereâ€™s still a limit for the number of bodies you can simulate and/or the precision with which you can do it.

Hope this helps!

3 Likes

in the getBodyGravitationForce function im getting this error

``````ServerScriptService.Script:17: attempt to perform arithmetic (add) on Vector3 and number
``````

the code

``````forceSum += G * body.mass * body2.mass / (distance * distance)
``````

Try

``````local direction = (body2.position - body.position).Unit
forceSum += direction * G * body.mass * body2.mass / (distance * distance)
``````

btw i forgot to ask how will i make a part go in orbit with this?

1 Like

This was my script btw which had the speed of orbit problem
Orbit.rbxl (43.5 KB)

How can a function(or variable) that just returns the distance between 2 points speed it up?

i think he meant i could check the distance of the two part and somehow speed it up when its closer but the thing is i dont even know how to speed it up lol

Magnitude is a property from the vector3 class

Okay, but the property does not define the speed

I know that Iâ€™m just correcting you.

1 Like

I couldnâ€™t understand, but magnitude doesnâ€™t define the speed so it wonâ€™t work

1 Like

why are you fixing that problem with it if you have a solution to my problem just say it or just dont talk at all not being rude here

This is the stupidest answer you will get, but I think you want the object to slow down at the left, and move faster at the right

time it, or be synchronous and check if the object has reached a certain distance