Fly Birdy! Fly! – 2D Curved Movement in Unity



Xander here…

I’m really pushing to get the flip book style 2D endless runner game we started at the beginning of the year finished.  The game is called Dog Run and as the title suggests is about taking your fun lovin’ pooch for a run – but watch out! There is a bunch of obstacles in your path – it’s a good thing you are such a natural jumper and can run all day.

If you want to do some beta testing of the game subscribe to this blog using the form on the right!

So I wanted to do a nice simple bird flying in the background to add a bit on interest (and also as a distraction for the player).  How hard do you think that would be?  It’s just a little birdy flapping about.  Whole games have been made with less!  It actually too me three days to get this little bird looking right.

In the beginning I started with just a straight fly-by  – a simple transform move that crossed the screen.

Straight


transform.position -= new Vector3(0.1f, 0, 0);

Not that exiting right? But you know – it’s a start.

 

I thought a little more about it and decided it would look better if there was a bit more movement.  I originally envisioned a sort of swooping dive from the top of the screen.

This got me a little closer but it looks really nothing at all like a bird would or could fly. A mechanical bird maybe – but not your darling little currawong.

ZigZag


if (updown)
{
target.position = new Vector3(transform.position.x - 2, transform.position.y - 2, transform.position.z);
updown = false;
}
else
{
target.position = new Vector3(transform.position.x - 2, transform.position.y + 2, transform.position.z);
var desiredRot = new Vector3(0, 0, -30);
updown = true;
}

Not such an elegant piece of code but it did what I wanted it to without a huge fuss.

 

ZigZag with Rotation

I tried to fix it a bit by adding in some rotation towards the direction being flown:


from.rotation = transform.rotation;
to.rotation = Quaternion.Euler(new Vector3(0, 0, 30));
transform.rotation = Quaternion.Lerp(from.rotation, to.rotation, Time.time * lspeed);

I really wasn’t liking where this was going.

Follow the Sine

I had the brainwave to start using a centre point and looping the bird around it with transform.RotateAround();  Which started off looking really good. But all I could do was get the bird to fly in circles – which started to look a little mad!

Finally after many attempts I found a method for using a Sine function that looked like it would work really well.  It meant adding a rigidbody to my object and a bit more overhead than I really wanted for a background character but what the heck I’d spent this much time on it – might as well have it look the way I wanted.


public Rigidbody2D rb;

public Transform target;    // A point on the far side of the screen to fly towards
public float speed;             //  I ended up between 2 and 3 in the inspector for this one
public float amplitude;     //  How high (or low) each wave would be - around 8 worked best
public float frequency;     // How many waves would run in the given time (2 to 4 was used)

private float startTime;
private Vector3 direction;
private Vector3 orthogonal;

void Start()
{
startTime = Time.time;
direction = (target.position - transform.position).normalized;    // Which way to head
orthogonal = new Vector3(-direction.z, direction.x, 0);               //  Which wave to catch!
}

void FixedUpdate()
{
float t = Time.time - startTime;
rb.velocity = direction * speed + orthogonal * amplitude * Mathf.Sin(frequency * t);
// The Black Magic
}

This worked a treat and with a bit of tuning was dipping and diving all over the shop!

 

All I needed to do next was to get a little rotation into the picture and we were totally flying!

Sine with Rotation


transform.right = -rb.velocity;

 

Thanks to: http://blog.shamanland.com/2016/03/move-by-sinusoid.html

For helping me understand what I wanted and for not protecting me from the details.


Leave a Reply

Your email address will not be published. Required fields are marked *