Optimizing a Solar System for other Physical Interactions

Note: this is a repost from scripting support as it most likely wasn’t in the right spot for attention

The Problem

Welcome to 'Lox:


A fully simulated gravity simulation where workspace.Gravity = 0, and it has a handy visualization script that the planet’s follow to a T.

But now I have a player, and their corresponding downward gravity force. And then I want to create a spaceship for the player, and that needs to be welded to the planet so it doesn’t just leave the player stranded. All of those interrupt the normal simulation.

So, currently the player sticks onto the ball quite nicely (thank you @EgoMoose) with some fake gravity:

To achieve that the part cannot have anything related to physics, because the player’s downward force could affect the planet’s positions and mess with the precarious state that is gravity. Therefore AlignPosition, VectorForce, and BodyForce can’t be used. Instead the position is updated in the script so that the downward force of the player does not affect the position of the planet.

However, that doesn’t help for welded items. Because the “WeldConstraint” or “Weld” doesn’t move the part since the position is being set by a script, which for some reason doesn’t update the weld. This presents an issue because I cannot add buildings or have spaceships “land” on the planet without having a script loop and update every single part of the model to make it seem like it’s attached.

Here’s what I’ve tried:

I’ve actually tried to use BodyVector, the part.Vector property, VectorForce, and the AlignPosition constraints to instigate movement. However they all have the same problems:

  1. The player’s downward force to simulate gravity affects the planet
  2. They do not accurately update the planet’s position, which causes it to lag behind the visualizer script.
  3. The “mass” of the planet affects the force exerted on the planet, despite the “Massless” being checked Frankly I’m convinced that it doesn’t do anything, though I could be incorrectly using it

I’ve tried to update the legacy weld’s C0 and C1 on every heartbeat of run service, but that causes the part to rapidly (basically every loop) switch the side of the planet the part is on (North pole to South pole to North . . .). Not to mention it’s rather taxing on the server’s performance.

What I have left to do:

The last two things I can do to maybe fix the problem is:

  1. Retest all the physical constraints with the “Massless” property checked to ensure that they didn’t affect anything (Player Gravity will still affect things though)
  2. Remove gravity simulation for planets, and simply have them on a set path. However that wouldn’t change anything, and would remove the idea behind the project.

TL;DR

My solar system with simulated gravity does not work with one more physical interaction. Player gravity exists but welds do not. How do I make other physical interactions work without destroying the precarious state of a stable orbit?

The script that each planet uses
--scripted by GreekForge
local module = function(script)
	local rs = game:GetService("RunService")
	local sets = require(game.ReplicatedStorage.UniverseSettings)
	
	local gConst = sets.GravitationalConstant
	local cBodies = workspace.CelestialBodies:GetChildren()
	local sRender = workspace.StartRendering --used in conjunction with the visualization script to help developers (like me) create stable orbits for their solar systems
	local plnt = script.Parent
	
	local vel = plnt.InitialVelocity.Value
	local pos = plnt.InitialPosition.Value
	
	plnt.Anchored = true
	
	repeat wait() until sRender.Value --nasty but I'm too lazy to actually change this
	
	plnt.Anchored = false
	
	rs.Heartbeat:Connect(function()
		for _, body in pairs(cBodies) do
			if body ~= plnt then --We don't want the planet to pull itself, makes no sense
				local dir = (body.Position - plnt.Position)
				local gForce = dir.Unit * (gConst * body.CustomMass.Value * plnt.CustomMass.Value) / math.pow(dir.Magnitude, 2)
				local gAccel = gForce / plnt.CustomMass.Value
				
				vel = vel + gAccel
			end
		end
		
		pos = pos + vel*(1/60) --1/60 here is used to stay consistent with the visualization script, using deltaTime here would result in minor inaccuracies between frame times that could "butterfly" into larger changes of orbits not seen in the visualization script.
		plnt.Orientation = Vector3.new(0, 0, 0)
		plnt.Position = pos
	end)
end

return module
4 Likes