# How to make a physics based 2D solar system?

Discussion in '2D' started by calebbabin, Mar 18, 2015.

1. ### calebbabin

Joined:
Mar 15, 2015
Posts:
5
So it turns out the unity community does not care for my problems D: however I figured out how to do this on my own, it does not change how much the sun is pulling on the planets based on distance but it fits my needs.

Code (CSharp):
1. using UnityEngine;
2. using System.Collections;
3.
4. public class Gravity : MonoBehaviour {
5.
6.     public Rigidbody2D Target;
7.     public Rigidbody2D Self;
8.     public float pull;
9.     public float initialForce;
10.     // Use this for initialization
11.     void Start () {
12.
15.     }
16.
17.     // Update is called once per frame
18.     void FixedUpdate ()
19.     {
20.
21.         Self.AddForce(Target.position - Self.position * pull); //object to orbit, self, pull of gravity
22.     }
23. }
24.
Because I'm an idiot I dont know how to get the rigidbody of the attached sprite so you have to set Self as the rigidbody of the planet and Target as the rigidbody of the sun.

Last edited: Mar 21, 2015
2. ### calebbabin

Joined:
Mar 15, 2015
Posts:
5
I'm still working on a version that will compensate for the distance from the sun and lower the gravitational pull and have the planets effected by each other based on how much mass nearby rigidbodies have. (I dont have much free time at the moment and I'm still learning the functions)

Any help would be appreciated.

3. ### DallyMoore

Joined:
Mar 17, 2015
Posts:
9

I've tried to do something like this 5 month ago , i found a lot of reference from this topic : http://forum.unity3d.com/threads/mario-galaxy-like-circular-gravity.33156/

And this tutorial :

Actually do something like that whitout raycast and only with joint it's pretty difficult.

If you are not familiar with raycast there are a lot of tutorial under the unity learn section , good luck c:

4. ### calebbabin

Joined:
Mar 15, 2015
Posts:
5
So it turns out that the equation for the pull of gravity is simply mass/(distance*distance) which makes thinks a hell of a lot easier. Here is the updated script which emulates gravity a lot more accurately by decreasing the pull the farther away the sun is.

Code (CSharp):
1. using UnityEngine;
2. using System.Collections;
3.
4. public class Gravity : MonoBehaviour {
5.
6.     public Rigidbody2D Target;
7.     public Rigidbody2D Self;
8.     public float pull;
9.     public float initialForce;
10.     // Use this for initialization
11.     void Start () {
12.
15.
16.     }
17.
18.     // Update is called once per frame
19.     void FixedUpdate ()
20.     {
21.         float dist = Vector2.Distance(Self.position,Target.position);
22.         float Gravity = (Self.mass + Target.mass) / (dist*dist);
23.             Self.AddForce (Target.position - Self.position * (Gravity * pull)); //object to orbit, self, pull of gravity
24.
25.     }
26. }
So now pull will increase the pull of gravity if over 1 and decrease if its below 1, this is so that you can adjust the gravity without having to go back and fourth to the different planets and the sun to get the perfectly balanced effect you want.
(although it will not be as accurate of a simulation if you use pull, I doubt anyone trying to simulate gravity exactly will be checking this post)

You could make a version of this script that only pulls objects towards the sun if their in its gravity well (like a sphere 100 units across) if you wanted to have a mini solar system with comically large planets.

I am still trying to find out how to have all of the planets orbit the sun and have gravity of their own effecting each other and comets.

Last edited: Mar 24, 2015
Reizla likes this.
5. ### blizzy

Joined:
Apr 27, 2014
Posts:
775
Wow, you're getting into complicated territory there. I know you're only doing it in 2D rather than 3D, but it sounds an awful lot like n-body simulation.

6. ### Reizla

Joined:
Nov 5, 2013
Posts:
136
This kinda is what I've been looking for as well, but then for a 3D environment. Right now I'm testing the script and it seems promising. The only thing I have to figure out though is how to create a (somewhat) stable orbit for my 'planet' around my 'sun (2 simple spheres, where the sun has 24 times the mass of the planet). I've played with pull and initial force a bit and so far /10 and *5 seems to work pretty well when the starting distance is rougly the mass of the 'sun' in units.

I'll let the test setup run a couple of hours and see where things end up and I'll come back on it...

### Unity Technologies

Joined:
May 24, 2013
Posts:
3,104
LiterallyJeff likes this.
8. ### Reizla

Joined:
Nov 5, 2013
Posts:
136
...couple of weeks...

I've tested the script, made some alterations here and there and it works perfectly for my 3D environment. I've also removed all UI input fields (other than the parent it's orbitting and 2 bool values) to make the script extremely flexible for large universes.

Code (CSharp):
1. using UnityEngine;
2. using System;
3. using System.Collections;
4.
5. public class SolarSystemController : MonoBehaviour {
6.
7.     isCenterStar=false; // Only toggles to TRUE when script is attached to CENTER STAR and no myParent is defined in UI
8.     public bool CounterRotate=false;
9.     public bool isDoubleOrbit=false; // Object is in an orbit around an object that's already in orbit - double the myPull of it!
10.     bool isStarted=false; // Only applies to bodies in orbit
11.     public Rigidbody myParent;
12.     Rigidbody mySelf;
13.     float myPull;
14.
15.     // Use this for initialization
16.     void Start () {
17.         mySelf=this.GetComponent<Rigidbody>();
18.         try { float test=myParent.mass; }
19.         catch { isCenterStar=true; }
20.         if (!isCenterStar) {
21.             // initialForce=SQRT(2*MassPlanet*PullOfGravity*(MassSun+MassPlanet))*35.42
22.             mySelf=this.GetComponent<Rigidbody>();
23. //            if(mySelf.mass<1) isMoon=true;
24.             myPull=mySelf.mass/myParent.mass*10;//*12.5f;
25.             if((float)(mySelf.mass/myParent.mass)>=0.05f && myParent.mass>10) myPull*=.125f; // We have a massive planet or even a 2nd star in orbit
26.             if(isDoubleOrbit) myPull*=2;
27.             float initialForce=Mathf.Sqrt(2*mySelf.mass*myPull*(myParent.mass+mySelf.mass))*35.42f;
28.             if(CounterRotate)initialForce*=-1;
30.             isStarted=true;
31.         }
32.     }
33.
34.     // Update is called once per frame
35.     void FixedUpdate () {
36.         if(!isCenterStar && isStarted) { // Only applies to bodies in orbit
37.             float dist = Vector3.Distance(mySelf.position,myParent.position);
38.             float myGravity = (mySelf.mass + myParent.mass) / (dist*dist);
39.             float parentVelocity=myParent.velocity.magnitude;
40.             if(parentVelocity==0) parentVelocity=1; // parent is center star - velocity should be 1 instead of 0
41.             mySelf.AddForce((myParent.position - mySelf.position) * (myGravity * myPull)*parentVelocity);
42.         }
43.     }
44. }
I realize that 3D!=2D, butthe basics are the same in Unity. Also note the auto calculation for the initialForce to kickstart the planet uses a 35.43 factor as constante. No clue where that number comes from (physically that is), but After a lot of trial and error on the kickstart calculations I found that number...

unityunity