I have been experimenting, trying to improve my workflow with coroutines, looking for a fast and safe shortcut to achieve all those common patterns; locks, timers, sequences, animations, tweens, all of them mixed, etc.
And after a fun week of coding and some testing, I just finished this dark magic: TeaTime, a fast & simple queue for timed callbacks, fashioned as a MonoBehaviour extension set.
Just put ‘TeaTime.cs’ somewhere in your project and call it inside any MonoBehaviour using ‘this.tt’ (and trust the autocomplete).
Unless I misunderstand, this will immediately start counting down as soon as you call the function DebugTextDelay, and then after delay, the Debug.Log(text) will execute?
This is not the same thing that I’m suggesting. I was thinking that you could add in a simple flag “enabled” or whatever, to control the processing of items in the given queue. In the above case it could be:
this.tt("queueName").Paused = true;
this.tt("queueName").Add(delay, () => Debug.Log("Hello!"));
...
//lots of wonderful stuff happening until we're ready to process the queue
...
this.tt("queueName").Paused = false;
This would be relevant when, say, users are causing a bunch of required actions that I only want to execute when they are done. So, I add each action to a queue, which gets processed when they click “done”, for example.
this.tt("queueName").ttStop();
this.tt("queueName").ttAdd(delay, () => Debug.Log("Hello!"));
...
// lots of wonderful stuff happening until we're ready to process the queue
...
this.tt("queueName").ttPlay();
Right now I cannot assure you TeaTime is optimal for mobile, I have been working mostly on the algorithm, workflow and patterns, and I still have some things to solve there. But of course this kind of optimizations are on my to-do for next versions, I’ll try my best handling those delegates.
Featuring ttPause, ttStop and ttPlay! And they work just like the word says, you can always see the changes log here.
I have this particular example showing those new features. The rest of the examples here, as usual (I’m starting to rethink the examples, maybe a tutorial, I have lots to do!)
Feel free to post your doubts here, or you can ask me personally on twitter.
Hope you like this update!
BONUS: I did made this game for Ludum Dare 32, Drybreed, play it and tell me what you think, powered by TeaTime v0.6.5 of course
There has been lots of changes since the last post here, I did a complete code rewrite, there is a cleaner API, better performance and TeaTime is now fully type-safe object-oriented. I’m so happy with this experiment!
Here are some examples / patterns! Give it a try!
// A simple 2 seconds delay.
TeaTime simpleDelay = this.tt().Add(2, () =>
{
Debug.Log("simpleDelay: Two seconds later, just once!" + Time.time);
});
// Something that repeats itself every 3 seconds.
TeaTime repeatDelay = this.tt().Add(() =>
{
Debug.Log("repeatDelay: Every 3 seconds, repeats forever! " + Time.time);
})
.Add(3).Repeat();
// A controlled frame by frame loop (update-like) with 1.5 seconds duration!
TeaTime updateLike = this.tt().Loop(1.5f, (ttHandler loop) =>
{
Debug.Log("updateLike: Frame by frame during 1.5 seconds, just once! " + Time.time);
});
// A simple delay without autoplay.
TeaTime somethingForLater = this.tt().Pause().Add(3, () =>
{
Debug.Log("somethingForLater: Someone called 'somethingForLater.Play()' 3 second ago! " + Time.time);
});
somethingForLater.Play();
// A tween-like with before and after setup.
TeaTime tweenLike = this.tt().Add(() =>
{
Debug.Log("tweenLike: Just before the 4 seconds loop! " + Time.time);
transform.position = new Vector3(999, 999, 999);
})
.Loop(4, (ttHandler loop) =>
{
transform.position = Vector3.Lerp(
transform.position,
Vector3.zero,
loop.deltaTime);
})
.Add(() =>
{
Debug.Log("tweenLike: Just after the 4 seconds loop! " + Time.time);
});
Probably my worst sin with TeaTime is that I’m using a generic list to store the queue. I should use an Array that automatically grows instead, because Unity doesn’t create garbage with arrays.
List<ttTask> _tasks = new List<ttTask>();
I haven’t made this change yet because it makes the code uglier, but it’s something that I’m planning to do!
Right now, by default, a TeaTime queue is non-destructive, so, every time you define a queue, the queue will stay that way, so you can use Play(), Pause(), Stop(), Repeat() or Immutable() to control your queue without worry about garbage.
But, if you are using Consume() mode (that deletes tasks after execution, a queue without memory) or Reset() that cleans everything, this will generates garbage. This will be fixed once I migrate to arrays.
Yes, the Chronos support should be possible by creating a TeaTime global manager, something that I’m experimenting with, to improve other stuff.
Doing a decent stress testing on most platforms and make the change to arrays is on my to-do! Soon I hope!