Coroutine
A coroutine is used to simplify the management of delayed tasks, whether time-based or frame-dependent. They excel in handling asynchronous operations and streamlining complex control flows, such as timers. Unlike regular functions that run straight through without stopping, coroutines can pause and resume their execution at designated points.
Summary
Importing the module
Yahaha provides a built-in module as a wrap and extension of Lua coroutine. To import the module:
local co = require("Utils.CoroutineHelper")
Functions
Wrap an async API with a callback function into a coroutine.
call an async function and return its value in a coroutine.
call an async function.
Wait until a condition is true in a coroutine.
Wait for t seconds and resume the given coroutine.
Wait for n frames and resume the given coroutine.
Stop a waiting coroutine.
Functions
wrap
Wraps an asynchronous API with a callback function into a coroutine. Each time the returned function is called, it resumes the coroutine.
Parameters:
func
(function): The asynchronous function to wrap.timeout
(number|nil): Optional timeout duration.
Returns: A function that resumes the wrapped coroutine.
Code samples
local co = require("Utils.CoroutineHelper")
local function SummingAsync(a, b, time,callback)
co.wait(time)
callback(a + b)
end
local summingCo = co.wrap(SummingAsync)
co.async(function()
print("start Summing")
local sum = summingCo(1, 2, 1)
print("Sum result: ".. sum)
end)
call
Calls an asynchronous function with a callback within a coroutine context. This function should not be called outside of a coroutine.
Parameters:
func
(function): The asynchronous function to call. Returns: The parameters passed by the async function to its callback.
Code samples
local co = require("Utils.CoroutineHelper")
local function SummingAsync(a, b, time,callback)
co.wait(time)
callback(a + b)
end
co.async(function()
print("start Summing")
local sum = co.call(SummingAsync,1, 2, 1)
print("Sum result: ".. sum)
end)
It can be useful with async methods such as resource load/scene load.
Usage example:
-
Find an audio clip in a package, for example "AMB_doom_drone_horror_dark_loop_1" from the extension package Horror Game Assets.
-
Add the script to an in-scene object.
-
Script to load and play this audio clip as BGM:
local co = require("Utils.CoroutineHelper")
local AudioManager = require("com.yahaha.sdk.audio.scripts.AudioManager")
local audioPath = "Packages/com.yahaha.sdk.horrorgameassets/Assets/Audio/EnvAudio/AMB_doom_drone_horror_dark_loop_1.wav"
script.OnStart(function(...)
co.async(function()
print("Start load bgm audio clip.")
local audioHandle = AudioManager.CreateBGMHandle()
local audioClip = co.call(YahahaMiddleLayerSlim.Resource.YaResourceManager.LoadAssetByPathAsync, audioPath)
if audioClip == nil then
printError("Failed to load BGM audio clip,audio path:" .. audioPath)
return
end
print("BGM audio clip loaded,audio name:" .. audioClip.name)
audioHandle:Play(audioClip, nil, true, 0)
end)
end)
-
Enter Play Mode to playtest the audio.
async
Starts an asynchronous function. This can be called both in the main thread and within a coroutine.
Parameters:
fun
(function): The asynchronous function to start. Returns: A thread representing the started coroutine.
Code samples
local co = require("Utils.CoroutineHelper")
co.async(function()
print("Hello!")
co.wait(1)
print("World!")
end)
co.async(function()
co.wait(2)
co.async(function()
print("Hey!")
co.wait(1)
print("Yahaha!")
end)
end)
waitUntil
Waits until a specified condition is true or until an optional timeout is reached. This function should only be called within a coroutine.
Parameters:
cond
(function): A condition function to evaluate.timeout
(number|nil): Optional timeout duration.
Returns: A boolean indicating whether the condition was met (true) or not (false).
Code samples
local co = require("Utils.CoroutineHelper")
local condition = false
co.async(function()
print("Waiting for condition to be true...")
co.waitUntil(function()
return condition
end)
print("Condition is true!")
end)
co.async(function()
co.wait(2)
condition = true
end)
wait
Suspends a coroutine for a specified duration and then resumes it. Should not be called out of coroutine with nil argument co
.
Parameters:
t
(number): The number of seconds to wait.co
(thread|nil): The coroutine to resume; if nil, resumes the running coroutine.
Returns: Void. However, if the wait
function is called with additional parameters beyond the required ones, these extra parameters will be returned to the coroutine once the wait period is over.
Code samples
local co = require("Utils.CoroutineHelper")
local function SummingAsync(a, b, time,callback)
co.wait(time)
callback(a + b)
end
step
Waits for a specified number of frames before resuming the given coroutine. Should not be called out of coroutine with nil argument co
.
Parameters:
n
(number|nil): The frame count to wait; defaults to 1 if nil.co
(thread|nil): The coroutine to resume; if nil, resumes the running coroutine.
Returns: Void. However, if the step
function is called with additional parameters beyond the required ones, these extra parameters will be returned to the coroutine once the wait period is over.
stop
Stops a running coroutine.
Parameters:
co
(thread): The coroutine to stop.
Returns: Void.
Code sample
local co = require("Utils.CoroutineHelper")
local printCo = co.async(function()
print("Hello")
co.wait(2)
print("World")
end)
co.async(function()
co.wait(1)
print("Stop print.")
co.stop(printCo)
end)