AnimationCurve: Not just for animations

Unity’s AnimationCurve is very useful when working with animations, but don’t let the name fool you, as it can be just as useful for non-animation purposes!

Using an animation curve is simple. Just add a public AnimationCurve field to your MonoBehaviour script.

public AnimationCurve myCurve;

And it will show up as a curve field in the inspector.

AnimationCurve field

Click the field to open the curve editor window. There you can shape the curve to your liking.

To get a value from the curve in your script, just call the following method:

var y = myCurve.Evaluate(x); 

That’s all there is to it!

Practical examples using AnimationCurve

In case I haven’t convinced you yet, let me show you some cases in which using AnimationCurve has been invaluable to me.

Drawing a difficulty curve

The first time I used AnimationCurve in this way, was for my Ludum Dare jam entry. It’s a simple game, where blocks drop from above and you have to push them to certain points to earn points and clear space for more dropping blocks. In order to increase the difficulty as the game progresses, the time between blocks dropping gets shorter.

Big Box Mania

I started by defining a linear progression between the easiest and hardest time intervals. The result was pretty boring, because I needed to ramp up the difficulty more quickly in the first couple of minutes. I moved on to writing a more complicated equation to get the right difficulty curve. This worked pretty well, but it turned out to be quite tricky and time-consuming to get it exactly right. So I started looking for a better solution.

Using an animation curve here turned out to be perfect, as it allowed me to simply draw a literal difficulty curve for my game! 😀

AnimationCurve difficulty curve

All that was left was a bit of code to tie everything together:

private void Update()
{
  // Keep track of the total playtime
  playTime += Time.deltaTime; 
  // Keep track of the time since the last block spawn
  spawnTimer += Time.deltaTime;  
  // Get the interval between spawns based on the current playtime
  spawnInterval = difficultyCurve.Evaluate(playTime / 60);

  if (spawnTimer >= spawnInterval)
  {
    spawnTimer = 0;
    Spawn();
  }
}

I used the same method recently for another game jam entry, to increase the interval at which enemies spawn.

Generating audio using AnimationCurve

A more complicated example where I used AnimationCurve is RetroKit‘s sound effect generator and music composer. The tones used to create sound effects and songs are generated using various types of waves (pulse wave, sine wave, sawtooth wave, etc.). Each wave results in a different sound. I created and stored these waves as animation curves.

AnimationCurve waveforms

This allowed me to generate samples for an AudioClip simply by calling the Evaluate method on the curve. Here’s a very simplified (untested and probably non-functioning 😉 ) version of RetroKit‘s implementation, that generates a single tone from an AnimationCurve.

// Pitch in hertz.
// Duration in seconds.
public AudioClip GenerateAudioClip(AnimationCurve curve, float duration, float pitch)
{
  // 44100 is the sample rate for the AudioClip.
  var samplesPerWave = 44100 / pitch; // The number of samples for a single wave.

  var numSamples = (int) (44100 * duration);
  var samples = new float[numSamples];
  for (var i = 0; i < numSamples ; ++i)
  {   
    // The curve represents a single wave, so if this sample is part of the second or greater wave, we need to have the index as if it were the first, to get the right value from the curve.
    var normalizedSampleIndex = i % samplesPerWave;
    var t = 1f / samplesPerWave * normalizedSampleIndex;
    samples[i] = curve.Evaluate(t);
  }

  var audioClip = AudioClip.Create("Generated Clip", samples.Length, 1, 44100, false);
  audioClip.SetData(samples, 0);
  return audioClip;
}

As an added bonus, I can use to the CurveField to easily visualize the waveforms for the user. And it opens up the possibility to implement the ability for users to define their own waveforms in a future release. 🙂

Conclusion

Hopefully, I’ve demonstrated how useful animation curves can be, outside of it’s originally intended purpose. I’d love to know if you’ve ever used AnimationCurve and if so, what for. 🙂

0 Comments

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>