Search code examples
c#unity-game-engineentity-component-system

Controlling Ship Rotation as it Orbits a Target


I am trying to get my ship entities to either look in the direction they are moving or at the target they are orbiting around. At this point I would be happy with either result. Unfortunately I simply don't seem to understand the underlying math enough despite all of my Google research on how to accomplish this.

This is what I currently have in my RotateSystem

public void Execute(ref Translation shipPosition, ref Ship ship, ref Rotation rotation)
{

      ship.Theta += .0075f;
      float3 delta = new float3(
          ship.Radius * Mathf.Sin(ship.Theta) * Mathf.Cos(ship.Phi),
          ship.Radius * Mathf.Cos(ship.Theta),
          ship.Radius * Mathf.Sin(ship.Theta) * Mathf.Sin(ship.Phi));


      rotation.Value = Quaternion.Slerp(rotation.Value,
          Quaternion.LookRotation(ship.OrbitTarget + delta-shipPosition.Value),0.5f);


      shipPosition.Value = ship.OrbitTarget + delta;           

}

The result of this is that ships face their orbit target 1/2 of the time and face away the other half of the time. enter image description here


Solution

  • Without the second parameter, Quaternion.LookRotation assumes you want the local up to be as close to Vector3.up as possible. Instead, use the direction from the orbiting body to the orbited body:

    public void Execute(ref Translation shipPosition, ref Ship ship, ref Rotation rotation)
    {
    
        ship.Theta += .0075f;
        float3 delta = new float3(
                ship.Radius * Mathf.Sin(ship.Theta) * Mathf.Cos(ship.Phi),
                ship.Radius * Mathf.Cos(ship.Theta),
                ship.Radius * Mathf.Sin(ship.Theta) * Mathf.Sin(ship.Phi));
    
        Vector3 previousPos = shipPosition.Value;
    
        shipPosition.Value = ship.OrbitTarget + delta;   
    
        rotation.Value = Quaternion.Slerp(rotation.Value, Quaternion.LookRotation(
                shipPosition.Value - previousPos,
                ship.OrbitTarget - shipPosition.Value), 0.5f);
    }