You could just use cos and sin just like when plotting a circle. That is not how I would do it but it is probably how many people would solve this problem and I think it actually might work well here.
This is how I approach problems (this one or any other):
- Look at your desired result:
You have clear illustrations defining the kind of motion you want to achieve… excellent!
We know we are dealing with motion so from this point on focus on that.
- Viewing the plane and the path it should follow what do we see?
We see a continual, incremental change in velocity.
I get that because I see that at one point the plane is heading straight to the right (1F, 0F) for example.
Later, it will end up heading straight up (0F, 1F) for example.
So, the problem can be seen as changing from (1F, 0F) to (0F, 1F) over time.
How much time will determine how big of a loop (circle) the plane moves in.
Consider, if the plane has a vector2 storing its current speed:
Vector2 v2CurSpeed;
v2CurSpeed.x = 1F;
v2CurSpeed.y = 0F;
By applying this to the plane’s current [transform] position the plane will move to the right slightly.
Now consider the plane has a second vector2 storing its current target velocity:
Vector2 v2TargetSpeed;
v2TargetSpeed.x = 0F;
v2TargetSpeed.y = 1;
When the plane reaches this target velocity it will be moving straight up.
It then becomes a very simple problem, right?
Incrementally, over time, the plane’s velocity needs to change from heading straight to the right to heading straight up.
You could use Lerp to do that.
What I’d do is simply have a method that is called during Update.
This method would gradually bring the plane’s current velocity to the target velocity.
A simple implementation would be:
private void AdjustCurrentVelocityToTargetVelocity()
{
if (v2TargetSpeed.x < v2CurSpeed.x)
{
v2CurSpeed.x -= 0.01F;
if (v2CurSpeed.x < v2TargetSpeed.x)
v2CurSpeed.x = v2TargetSpeed.x;
}
else if (v2TargetSpeed.x > v2CurSpeed.x)
{
v2CurSpeed.x += 0.01F;
if (v2CurSpeed.x > v2TargetSpeed.x)
v2CurSpeed.x = v2TargetSpeed.x;
}
if (v2TargetSpeed.y < v2CurSpeed.y)
{
v2CurSpeed.y -= 0.01F;
if (v2CurSpeed.y < v2TargetSpeed.y)
v2CurSpeed.y = v2TargetSpeed.y;
}
else if (v2TargetSpeed.y > v2CurSpeed.y)
{
v2CurSpeed.y += 0.01F;
if (v2CurSpeed.y > v2TargetSpeed.y)
v2CurSpeed.y = v2TargetSpeed.y;
}
}
4 target velocities and the transitions between them are enough to represent this loop motion.
private enum TargetVelocityType
{
Right,
Up,
Left,
Down
}
Adding a type to represent which target velocity we are transitioning to:
TargetVelocityType eTargetVelocityType = TargetVelocityType.Right
Then we just check if curSpeed = TargetVelocity we move on to the next velocity in the pattern:
if eTargetVelocityType == Right it becomes Up. Up becomes Left. Left Becomes Down. And Down cycles back to Right if you want to keep the looping going.
If you implemented the above you would end up with an object moving in a circular motion.
The 0.01F can be adjusted to determine how quickly the plane adjusts from its current velocity to the target velocity.
You may also want to normalize the new velocity.
Basically, for all of this stuff there are many different solutions. Some people immediately go to math (such as sin() and cos() in this case), others would use some kind of predefined motion paths, etc. None are the wrong way. None are the right way. What I have shown you here is not the wrong way or the right way. It is just showing how I break a problem down into simple steps. You do that to identify the fundamental parts. Once you have those fundamentals it is easy to code up a solution. And this is certainly not the only way to implement the solution. I could have approached the implementation in various ways focusing on the velocities and each implementation would result in basically the same visible result in the end.