How to make a planet orbit a star?

I’m attempted to simulate a planet’s orbit around a star. I want to make this orbit as accurate as possible. Here is the code I have so far in c++ which simulates an object going in a straight line.

void ARotating_sphere::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	time += DeltaTime;

	NewLocation = GetActorLocation();
	FVector Distance = FVector((NewLocation.X - StarLocation.X), 0, (NewLocation.Z - StarLocation.Z));


	Direction.X += ((Force.X) / mass1) * DeltaTime;
	NewLocation.X += Direction.X * DeltaTime;

	Direction.Z += ((Force.Z) / mass1) * DeltaTime;
	NewLocation.Z += Direction.Z * DeltaTime;


	Force.X = ((Mass1 * Mass2) / pow(Distance.X,2));
	Force.Z = ((Mass1 * Mass2) / pow(Distance.Z,2));
	
	SetActorLocationAndRotation(NewLocation, NewRotation, false, 0, ETeleportType::None);

}

What I’m doing is I’m updating the position and velocity. For the velocity I’m taking the current velocity and adding the acceleration (which is force/mass) and for the position and taking the current position and adding the velocity. As for the force, I’m using an equation which adjusts the force based on how close the planet is to the star. You can also see that for distance that I’m setting y to is 0. This is because for this particular animation, I don’t need to use the y position. Now this works if I just need to move an object in a straight line. What I’m trying to do now is take this code and make it that the planet moves in a circle around the sun.

I tried using sin(time) and cos(time) which worked for moving the planet around the sun but for an orbit, I want the rotation to speed up when it gets close to the star. That’s what those two force equations are. The force is calculated by multiplying the mass of the planet and star and then dividing it by the distance between them. So if the planet is closer to the start then the rotation will go faster.

So how can I take this code and change it into an orbit.

So what you are doing now is performing a translation in 2D space according to some constant force aka the resulting velocity, am I right? (Btw, maybe rename Direction into Velocity, thats more physically accurate :wink: )

So you update the position like

p2 = p1 + T

with T being the translation vector T = (T.x, T.z) = velocity * time = (v.x, v.z) * dt (delta time)

And what you need now is adding also a Rotational component:

p2 = R * p1 + T

with R being the 2D rotation matrix around an angle a, then we get

p2.x = p1.x cos(a) - p1.z sin(a) + t.x

p2.z = p1.x sin(a) + p1.z cos(a) + t.z

Now the next question: how to we get the angle a? its by using Angular velocity

w = a / dt = v / r

a = v / r * dt

w is the angular velocity (radians per seconds), v is the velocity magnitude and r is the radius (=distance) magnitude

So lets modify your code a little - No garantee it´s working, I did not test it. :wink:

  float XZVector2Magnitude(FVector v) {
     return sqrt(pow(v.X, 2) + pow(v.Z, 2));
}

void ARotating_sphere::Tick(float DeltaTime)
 {
     Super::Tick(DeltaTime);
     
     time += DeltaTime;
 
     OldLocation = GetActorLocation();
     FVector Distance = FVector((OldLocation.X - StarLocation.X), 0, (OldLocation.Z - StarLocation.Z));
 
     // I would calculate the force first 
     Force.X = ((Mass1 * Mass2) / pow(Distance.X,2));
     Force.Z = ((Mass1 * Mass2) / pow(Distance.Z,2));

     Velocity.X += ((Force.X) / mass1) * DeltaTime;
     Velocity.Z += ((Force.Z) / mass1) * DeltaTime;
     float Angle = XZVector2Magnitude(Velocity) / XZVector2Magnitude(Distance) * DeltaTime;
     
     NewLocation.X = OldLocation.X * cos(Angle) - OldLocation.Y * sin( Angle) + Velocity.X * DeltaTime;
     NewLocation.Z = OldLocation.X * sin(Angle) + OldLocation.Y * cos(Angle) + Velocity.Z * DeltaTime;

     
     SetActorLocationAndRotation(NewLocation, NewRotation, false, 0, ETeleportType::None);
 
 }

Another Point - if you really want to simulate accuratly, you should add the Gravitational constant to your force calculation.