1
\$\begingroup\$

I got this code from somewhere else, I want to implement Kepler's third law to make the simulation look more realistic, the simulation is a 2D satellite orbiting around a planet, the satellite(Planet) script here is :

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Planet : MonoBehaviour {
private float alpha; //will use for cos & sin (as angle)
private float distance;//distance from center
private float Rotation;//rotation angle
private float currentTime;//Time start when Instantiated
//input values
public float speed;
public Vector2 RotationValues;
public Vector2 distanceValues;
public Vector2 sizeValues;


void Start () {
    //Initialize with Random rotation & distance & size

    //Random Rotation between -2 & 2
    Rotation = Random.Range(RotationValues.x, RotationValues.y);
    //Random distance  between -1 & 2
    distance = Random.Range(distanceValues.x, distanceValues.y);
    //Random Size between 0.2f & 0.7f
    var Size = Random.Range(sizeValues.x, sizeValues.y);
    //Set localScale with random size
    transform.localScale = new Vector3(Size, Size, Size);

    //calculating current time by subtraction Time.time and lastTime
    currentTime = Time.time - Generator.lastTime;

    //GetComponent<MeshRenderer>().material.color = new Color(Random.value, Random.value, Random.value); //Random Color
}

void Update () {
    //Timer
    currentTime += Time.deltaTime;

    var X =  (distance * Mathf.Cos(currentTime)); //X
    var Y =  (distance * Mathf.Sin(currentTime)); //Y
    var R = (Rotation * Mathf.Cos(currentTime)); //Rotation
    //give earth from generator class
    var Earth = Generator.Earth;
    transform.position = Earth.transform.position + (new Vector3(X, R, Y));// RotateAround Earth

}
}

also I have this other script which generates the planets:

using UnityEngine;
using System.Collections;

public class Generator : MonoBehaviour {
public GameObject prefab;
public static GameObject Earth;
public static float lastTime;
public int numerOfSatellites;


void Start() {
    Earth = GameObject.FindGameObjectWithTag("MainPlanet");//Find Earth
    for (int i = 1; i <= numerOfSatellites; i++) {
        lastTime = Time.time;
        GameObject sat = Instantiate(prefab, Earth.transform.position, Quaternion.identity);
        Physics2D.IgnoreCollision(sat.GetComponent<CircleCollider2D>(), Earth.GetComponent<CircleCollider2D>());
    } }
}

I know that the main part here is

void Update () {

    //Timer
    currentTime += Time.deltaTime;

    var X =  (distance * Mathf.Cos(currentTime)); //X
    var Y =  (distance * Mathf.Sin(currentTime)); //Y
    var R = (Rotation * Mathf.Cos(currentTime)); //Rotation

    //give earth from generator class
    var Earth = Generator.Earth;
    transform.position = Earth.transform.position + (new Vector3(X, R, Y));// RotateAround Earth

}

The main problem is that whatever distance the planets have from the mainPlanet (called earth) they move at the same angular velocity, how would I change this? enter image description here enter image description here enter image description here enter image description here

Those are the basic 4 steps of every orbit, the problem here is that they all align in the center, which shouldn't be possible because of the random distances they have

\$\endgroup\$
  • \$\begingroup\$ When you say, "move at the same speed", do you mean they move an equal number of degrees / radians per second, about the sun? i.e. same angular velocity? \$\endgroup\$ – Engineer Apr 24 '17 at 19:49
  • \$\begingroup\$ They move an equal number of degrees, as I put an image example on the question, they all align in the center, which explains that they all move the same angular velocity \$\endgroup\$ – Lendrit Ibrahimi Apr 24 '17 at 20:34
  • 2
    \$\begingroup\$ Specifically with regard to the behaviour of slowing at a distance and speeding up around the closest approach (periapsis), this other question "Kepler orbit : get position on the orbit over time" might be a closer duplicate. \$\endgroup\$ – DMGregory May 1 '17 at 20:21
3
\$\begingroup\$

Kepler's third law states that the square of the period c of revolution is proportional to the cube of the distance c

a

or equivalently

period

Now, the function b has a period of b.

You can change the period by changing c. If you want it to satisfy Kepler law, you have introduce a dependence on the distance c

b

so that

last

where C is a constant that physically should make the argument of the cosine dimensionless. You do not need to worry about it in the code though, so you can set it to 1.

In conclusion, just change your update function in this way

void Update () {

   //Timer
   currentTime += Time.deltaTime;

   var prefactor = Mathf.Pow(distance, -2/3);
   var X =  (distance * Mathf.Cos(prefactor * currentTime)); //X
   var Y =  (distance * Mathf.Sin(prefactor * currentTime)); //Y
   var R =  (Rotation * Mathf.Cos(prefactor * currentTime)); //Rotation

   //give earth from generator class
   var Earth = Generator.Earth;
   transform.position = Earth.transform.position + (new Vector3(X, R, Y));// RotateAround Earth

}
\$\endgroup\$
1
\$\begingroup\$

You have a fixed angular velocity for each planet.

The easiest way to fix this without changing much of your current code is to modify the code so that the angular change per Update() is inversely proportional to the orbital radius of the planet.

Let's assume Earth is at radius 2. Let's assume Jupiter is at radius 10. 10/2 = 5, thus you need to divide the angular change for Jupiter by 5 to get it to have roughly the same linear velocity as earth; this works because the formula for circumference, c = 2πr, is linear. Of course you may not want the same linear velocity; but this at least gives you a basis to work from, and you can then (randomly) adjust velocity of each heavenly body, from there.

The more difficult but also more rigourous way would be to use physics to correctly update the position of each planet on each FixedUpdate(), using vectors. This ranges from quite simple to pretty complex, depending on how much of the physics you want to explicitly control, for example, going as far as calculating mass per body may not be necessary, but adjusting the motion vector each update according to the gravity force being applied, would seem to be a sane requirement.

\$\endgroup\$
  • \$\begingroup\$ The problem is that the actual way they move is by changing their position, so i can't really do much with their velocity \$\endgroup\$ – Lendrit Ibrahimi Apr 25 '17 at 20:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.