Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

How to make a physics based 2D solar system?

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

  1. calebbabin

    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.        
    13.         Self.AddForce(Vector2.up * initialForce); //add initial orbital velocity
    14.         Self.AddTorque(100f); //add rotation
    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

    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

    DallyMoore

    Joined:
    Mar 17, 2015
    Posts:
    9
    (sorry for my bad english)

    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

    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.      
    13.         Self.AddForce(Vector2.up * initialForce); //add initial orbital velocity
    14.         Self.AddTorque(100f); //add rotation
    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

    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

    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...
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    3,104
  8. Reizla

    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;
    29.             mySelf.AddForce(Vector3.forward * initialForce); //add initial orbital velocity
    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