Featured image of post Momentum – Unity Timing Asset

Momentum – Unity Timing Asset

A custom tweening library for Unity.

A game without anticipation is like playing tennis in the dark.

Games require anticipation, and anticipation requires animation.

Games are dynamic systems, and so they require dynamic animations. In order to do dynamic animations, we have to write code that can start, wait, stop and sequence actions.

There are many ways to do this, from manually checking a timestamp every frame to using a tweening library.

For a while, I’ve been using Unity’s coroutines. They’re great because they present the logic in sequential order. But they are somewhat cumbersome to write, even for small things.

I wanted to write a timing library that would take care of all the boilerplate code and allow me to make dynamic animations as easily as possible.

Example

Here’s an example of a time counter. The count increases and the graphics scale up and down every second.

Without Momentum

// Keep track of variables
int count = 0;
float currentTime = 0f;
float time = 1f;
Text text;

// In update loop
void Update()
{
  // Add current time...
  currentTime += Time.deltaTime;
  // Did we pass 1 second?
  if (currentTime >= time)
  {
    // Reduce 1 second and increase the loop count
    currentTime -= time;
    count++;
  }
  // Get the unit progress of the current animation
  float progress = currentTime / time;
  // Set text to current loop number
  text.text = count.ToString();
  // Scale the counter text up and down
  text.transform.localScale = Vector3.one * (Ease.InOutSine(progress * 2f) + 1));
}

With Momentum

void Start()
{
  // Create and run a new task
  Task.Run()
    // every 1 second
    .Duration(1f)
    // Repeat forever
    .Loop()
    // Set text to 0
    .OnStart(task => text.text = task.CurrentLoop.ToString())
    // Scale the counter text up and down
    .OnUpdate(task => text.transform.localScale = Vector3.one * (Ease.InOutSine(task.Progress * 2f) + 1))
    // Set text to current loop number
    .OnLoop(task => text.text = task.CurrentLoop.ToString());
}

Complexity

The basic system was fairly simple to write. You queue in tasks and execute them all at once. When a task completes you check if it has a next task defined, which you’d queue in to be started in the next update.

I was a little surprised at how much complexity followed:

  1. Ordering tasks: sometimes one task needs to run before another.
  2. Destroying tasks: some tasks need to be linked to a game object otherwise you’ll get null reference exceptions.
  3. Testing: all kinds of issues like cyclic tasks.
  4. Performance: pooling tasks instead of constantly creating and destroying new ones.
  5. Writing Modules: we often animate the same things over and over again (Transformations, Colors, Audio).

Uses

The library was used in Turbo Balls and Swords and Forks. And while I love it, I don’t plan on using it in the future. There are far better tweening libraries out there like DOTween.

Code

https://github.com/IggyZuk/momentum

Takeaways

  • Harder than you think – just use DOTween or another tweening library.
Last updated on Feb 13, 2021 19:54 UTC
Built with Hugo
Theme Stack designed by Jimmy