# Maintain a set orbit(circumfrence) at variable speeds

Hi there, I’m pretty new with Unity and game development so apologies upfront.

I am trying to figure out how to maintain a set orbit at variable speeds using a rigidbody and the addforce function.

I’m not a real mathy sort of guy but my simple mind seems to think if I can estimate how many game units the object is likely to travel foreword based on the force applied in the current frame I could then calculate the circumference and plot the point on the circumference based on the objects forward movement?

So, I would need to know how far forward the object will travel BEFORE the physics engine applies the force for the frame so I can aim the object correctly and not exceed the boundary of the circumference? As the speed changes the next point on the circumference would change and so would the rotation of the object?

Is there a hopefully much simpler way to use rigidbody physics and maintain a precise distance from the object being orbited at variable speeds?

Would anyone with experience in these things at least be able for confirm if this is a stupid question or a difficult one?

Thanks!

You can do this fairly easily by thinking of it as an orbit of a satellite around a planet. The satellite is accelerated to a specific velocity, and once the engines are cut it continues to orbit around the planet.

``````using UnityEngine;
using System.Collections;

public class Orbit : MonoBehaviour {

[SerializeField]
Transform target;

[SerializeField]
float initialVelocity = 10.0f;

private Rigidbody rigidbody;

void Awake()
{
rigidbody = GetComponent<Rigidbody>();
}

void Start()
{
SetVelocity();
}

void FixedUpdate ()
{
SetVelocity();

Vector3 dir = (target.position - transform.position).normalized;
Vector3 cross = Vector3.Cross(Vector3.up, dir).normalized;

}

void SetVelocity()
{
Vector3 dir = (target.position - transform.position).normalized;
Vector3 cross = Vector3.Cross(Vector3.up, dir).normalized;

rigidbody.velocity = cross * initialVelocity;
}
}
``````

The object is initial pushed in a direction perpendicular to the vector pointing towards the target, and from there the “planet” exerts a force equal to v^2/d, where v is your velocity and d is the distance from the planet. You can play around with the initialVelocity value while in play mode to see that it works even if the velocity is changed on the fly.

1 Like

Hi Iron-Warrior, thanks for the script. When you say “the “planet” exerts a force equal to v^2/d” you mean to simulate a decaying orbit? I’ve set the script up and that was what I gathered from watching it in action. I need the object to maintain a set distance from the object with no simulated pull from the planet. Just a circular set orbit that can change speeds without effecting the circumference of the radius. Set a distance away from the object and no matter what speed the orbiting object is traveling the radius/circumference stays the same? I’m intending to try and pick apart what you’ve posted above but it’s going to take me awhile with my current math skills.

I was thinking I could just set a max speed for the object rotating, find the max amount I have to turn to stay the correct distance away from the object. Then if the object is moving at a slower speed adjust the turn amount based on what percentage of full speed I am traveling?

Or maybe just take some math classes…lol. Thanks though, man. Very much appreciated.

Ahh…okay. I took a guess and removed the part that looked like it was responsible for the planets gravitational pull and it looks to work the way I need now :

became :

Thanks again, Iron!

Actually, no, the orbit circumference still gets larger at greater speeds, darn.

Okay, so if you want to maintain a set distance away from an object at variable speed and you have to work with a frame rate that allows you to rotate an object and move it forward at set increments you would have to be able to predict how far forward the object was likely to move so that you could calculate the correct amount to turn the object so that is does not exceed the orbit circumference?

Hmm. Is it essential that you use AddForce? If not, it’s pretty simple to just rotate the object around it’s target orbit.

``````using UnityEngine;
using System.Collections;

public class SimpleOrbit : MonoBehaviour {

[SerializeField]
Transform target;

[SerializeField]
float angularVelocity = 10.0f;

[SerializeField]

Rigidbody rigidbody;

void Awake()
{
rigidbody = GetComponent<Rigidbody>();
}

void Start()
{
transform.position = target.position + Vector3.right * orbitRadius;
}

void FixedUpdate()
{
Vector3 localPos = target.InverseTransformPoint(transform.position);
localPos = Quaternion.AngleAxis(angularVelocity * Time.deltaTime, Vector3.up) * localPos;
Vector3 worldPos = target.TransformPoint(localPos);

rigidbody.MovePosition(worldPos);
}
}
``````

This script just transforms the “ship” position into local coordinates with respect to the “planet”, and then rotates it around the planet.

The original script I posted should not have any orbital decay, but after testing it at faster speeds I noticed that it did eventually decay in! Debugging it I found that setting the velocity each frame was causing some sort of imprecision…I fixed that, so the script now works for a constant orbit velocity using forces (but not variable, as you originally wanted).

``````using UnityEngine;
using System.Collections;

public class Orbit : MonoBehaviour {

[SerializeField]
Transform target;

[SerializeField]
float initialVelocity = 10.0f;

[SerializeField]

private Rigidbody rigidbody;

void Awake()
{
rigidbody = GetComponent<Rigidbody>();
}

void Start()
{
transform.position = target.position + Vector3.right * orbitRadius;

SetVelocity();
}

void FixedUpdate ()
{
// SetVelocity();

Vector3 dir = (target.position - transform.position).normalized;

DebugDraw.DrawVector(transform.position, rigidbody.velocity, 1.0f, 1.0f, Color.yellow, 0, false);
}

void SetVelocity()
{
Vector3 dir = (target.position - transform.position).normalized;
Vector3 cross = Vector3.Cross(Vector3.up, dir).normalized;

rigidbody.velocity = cross * initialVelocity;
}
}
``````

If it is essential that you use forces for whatever reason we’ll have to think of something else! The issue with using forces is that in a real-world setting, the ship’s force direction is affected by either a gravitational force (like a planet) or is turned in an atmosphere (that would have drag).

1 Like

rigidbody.MovePosition might be an option actually. I was hoping to try to maintain the use of rigidbody.Addforce because other game play elements may require rigidbody.Addforce and I wasn’t sure how well that would work if I incorporated a point to point style movement system and then try to use rigidbody.Addforce at other points in the game.

Do you know if there is anyway to access where the physics engine has resolved to move an object that has velocity before it does so inside the Fixed Update? If I can figure out how far forward the ball will move in the given frame I think I can calculate the rotation(the intersection of the radius and forward movement).

I’m going to monkey around with the script using moveposition and see where that gets me.

Ha! The script with the decaying orbit was cool though. I’m totally saving both the decaying version and the “fixed” version for future use. Thanks again, Iron!

For rotation, in the script I posted (that is using MovePosition), you can use Quaternion.LookRotation to point the ship in the direction of travel (which is what I assume you mean when you say to rotate it). These two lines placed above the rigidbody.MovePosition call will do that.

``````Vector3 direction = worldPos - transform.position;

rigidbody.MoveRotation(Quaternion.LookRotation(direction, Vector3.up));
``````

Edit: On the subject of using AddForce, unless you really need objects to correctly bounce off each other and walls, there isn’t really any reason to.

1 Like

Thanks Iron, I’m going to mess around with your suggestions and post back in a bit. Much appreciated again, man.