- Home /
How to have realtime months/years pass in seconds
Hi, I would like to have a simulation with certain physics and these things happen very slowly. I want to visualize the orbit of the moon in a year around the earth in seconds.
I have seen the option of modifying Time.TimeScale, but it only allows up to a value of 100. This would force me to wait for 3 days to view a whole year.
Any help would be appreciated.
Answer by lgarczyn · Nov 26, 2019 at 05:24 AM
Showing the code you currently use would help a lot. But basically, you don't need physics for that. Stable orbits are very close to an ellipsis, and can be often reduced to a circle.
Every update, simply update a timer by Time.deltaTime times your variable speed, and have a function that deduces the position from that timer, using the formula of an ellipsis. If you use circles, the formula is simple:
Vector3 moonPosition = axialTiltQuaternion * Quaternion.AngleAxis(Vector3.up, timer) * Vector3.forward * lunarDistance + earthPosition;
If you want to go the path of physics, you need a dynamic rigidbody, and every frame use AddForce towards the earth. The force needs the ForceMode.Acceleration, and needs to be divided by the distance to earth times itself. The mass of the rigidbody is irrelevant. Now:
Chose a scale, like 1/1,000,000, and set up your earth and moon at their real-life smallest distance from each other, times your scale.
Set up the starting velocity to the velocity of the moon compared to earth when it is closest, also times the scale.
Every frame add the gravitational force, which is
(G * mass of the moon * mass of the earth * your scale squared) / (the unity distance between the earth and the moon squared)
This will give you a real-time orbit. To make it faster, simply multiply the starting velocity and the force by your desired timescale (100,000/1 for a lunar orbit every ~25 seconds).
Because your are dealing with very large numbers, it might be better to simplify the multiplications beforehand, to make sure no precision is lost. For example, group the timescale and scale multiplication together at the start of the formula, and/or use doubles instead of floats to calculate the force and velocity.
If this is too complicated, feel free to ask any questions.
Hello Ceandros,
I was actually trying the second approach you mentioned. Turns out I was having issues with the scale... and when testing the moon orbit it took too long to visualize if the behaviour was correct.
I followed your scale tips and now I got a proper orbit working and with easy simulation speed (added to the scale). Thanks a lot.
For reference this is the code I used:
//To keep the orbit an initial speed has to be added to the object:
double velocity = $$anonymous$$ath.Sqrt(GRAVITATIONAL_CONSTANT * mass_earth / ((earth.transform.position - transform.position).magnitude* _spaceScale))/ _spaceScale;
//Set up the scale:
_spaceScale = 6000000 / 100; //6000000 is my scaling factor. 100 is the speed up.
//Update the gravity pull on the object
_direction = target.transform.position - transform.position; //Vector3
double distance = (_direction.magnitude * _spaceScale);
_earthGravity = (float)(target.GetComponent<Earth>().GetGravityPull(distance)/ _spaceScale);
_rigidbody.AddForce(_direction.normalized * _earthGravity, Force$$anonymous$$ode.Acceleration);
//GetGravityPull(double distance$$anonymous$$etersFromObject)
return GRAVITATIONAL_CONSTANT * _mass_earth / $$anonymous$$ath.Pow(distance$$anonymous$$etersFromObject, 2); //In meters
All this is quick prototyping, so it can probably be optimized and be written in a nicer way :)