I watched a youtube video on some gravity simulation, and they let you see the source code, so I had this idea to recreate it in Roblox, but it was created with C# in Unity. Now I was sort of able to figure out what the code does but I wasn't sure so I did a few google searches if I didn't understand something. Now the thing is SOMETHING isn't right with it because the planets just follow each other and speed up over time until you experience floating-point precision errors, so I want to know, how good is my code? Here's the source: https://github.com/SebLague/Solar-System/tree/Episode_01/Assets/Scripts/Planets Here's my code: (I didn't do gravity object because it appeared to do nothing) Universe: (ModuleScript)

local Universe = {
	gravitationalConstant = 0.0001;
	physicsTimeStep = 0.01;
};

Universe.updateProperties = function(G, T)
	Universe.gravitationalConstant = G
	Universe.physicsTimeStep = T
end

return Universe

CelestialBody: (ModuleScript)

local Universe = require(script.Parent.Universe)
_G.CelestialBody = {}

newCelestialBody = function()
	local this = {}
	
	this.radius = 0
	this.surfaceGravity = 0
	this.initialVelocity = Vector3.new(0, 0, 0)
	this.bodyName = "Unnamed"
	
	this.velocity = Vector3.new(0, 0, 0)
	this.mass = 0
	this.rb = game.ServerStorage.MeshPart:Clone()
	this.rb.Parent = workspace
	local mv = Instance.new("IntValue", this.rb)
	mv.Name = "mass"

	this.Awake = function()
		this.rb.mass.Value = this.mass
		velocity = this.initialVelocity
	end
	
	this.UpdateVelocity = function(allBodies, timeStep)
		for i,otherBody in pairs(allBodies) do
			if otherBody ~= this then
				local sqrDst = (otherBody.rb.Position - this.rb.Position).Magnitude
				local forceDir = (otherBody.rb.Position - this.rb.Position).Unit
				local acceleration = forceDir * Universe.gravitationalConstant * otherBody.mass / sqrDst
				velocity += acceleration * timeStep
			end
		end
	end
	
	this.UpdateVelocity = function(acceleration, timeStep)
		velocity += acceleration * timeStep
	end
	
	this.UpdatePosition = function(timeStep)
		this.rb.Position += (velocity * timeStep)
	end
	
	this.OnValidate = function()
		this.mass = this.surfaceGravity * this.radius * this.radius / Universe.gravitationalConstant
		this.rb.Size = Vector3.new(1, 1, 1)* this.radius
		this.rb.Name = this.bodyName
	end
	
	this.rb.Changed:Connect(this.OnValidate)
	
	this.RigidBody = function()
		return this.rb
	end
	
	this.Position = function()
		return this.rb.Position
	end
	table.insert(_G.CelestialBody, this)
	return this
end

return newCelestialBody

NBodySimulation: (ModuleScript)

local Universe = require(script.Parent.Universe)
local Time = {fixedDeltaTime = 0}

function newNBodySimulation()
	local this = {}
	this.bodies = _G.CelestialBody
	this.NBodySimulation = Instance.new("Folder", workspace)
	
	this.Awake = function()
		this.bodies = _G.CelestialBody
		Time.fixedDeltaTime = Universe.physicsTimeStep
		print("Setting fixedDeltaTime to: "..Universe.physicsTimeStep)
	end
	
	this.FixedUpdate = function()
		for i = 1, #this.bodies do
			local acceleration = this.CalculateAcceleration(this.bodies[i].Position(), this.bodies[i])
			this.bodies[i].UpdateVelocity(acceleration, Universe.physicsTimeStep)
		end
		
		for i = 1, #this.bodies do
			this.bodies[i].UpdatePosition(Universe.physicsTimeStep)
		end	
	end
	
	this.CalculateAcceleration = function(point, ignoreBody)
		local acceleration = Vector3.new(0, 0, 0)
		for i,body in pairs(this.bodies) do
			if body ~= ignoreBody then
				local sqrDst = (body.Position() - point).Magnitude
				local forceDir = (body.Position() - point).Unit
				acceleration += forceDir * Universe.gravitationalConstant * body.mass / sqrDst
				print(acceleration)
			end
		end
		return acceleration
	end
	
	this.Bodies = function()
		return this.bodies
	end
	
	this.NBodySimulation = function(instance) 
		if instance == nil then
			instance = this.NBodySimulation
		end
		return instance
	end
	return this
end

return newNBodySimulation

Heres an example script to demonstrate usage:

local CelestialBody = require(script.Parent.CelestialBody)
local NBodySimulation = require(script.Parent.NBodySimulation)
local planet = CelestialBody()
planet.radius = 2.5
planet.surfaceGravity = 10
planet.bodyName = "New planet"
planet.initialVelocity = Vector3.new(0, 0, 0)
planet.OnValidate()
planet.Awake()
local sim = NBodySimulation()
sim.Awake()

wait(10)

while true do
	sim.FixedUpdate()
	wait()
end

4 comments

0

The scope of this questions really is way too large. We don't have all the details, and seeing as this is translated code from an OOP language to a scripting language, how are we to know if the problem resides in the source's code that you translated it from or with your translated code, or just that roblox's engine can't handle what you are trying to do.

0

Instead of asking "How is this code", try to figure out the problem for yourself, and then come back with a few more specific questions.

0

It's not the source code, it works just fine in the game.

0

The Unity game, I mean.