關於協程就不多說了,隨便一搜就有一堆關於協程的介紹和使用,直接看我要解決的問題吧:等一個協程執行完成再執行後面的邏輯。應用場景:等遊戲開始動畫執行完成,才能開啓遊戲邏輯;等洗牌完成才能進行發牌邏輯…
Unity 之 Lua模擬C#等一個協程執行
在 C# 中的使用方式:
在C#中使用使用 yield return StartCoroutine(fun()) 來處理,看下測試代碼:
執行順序爲: 調用協程 Cor2 執行自己的邏輯,然後調用協程 Cor1 並且等協程 Cor1 執行完成之後,在繼續執行Cor2自己後面的邏輯;
private void OnEnable()
{
StartCoroutine(Cor2());
}
private IEnumerator Cor1()
{
Debug.Log("Cor1 1111111111111111");
yield return new WaitForSeconds(2f);
Debug.Log("Cor2 2222222222222222");
}
private IEnumerator Cor2()
{
Debug.Log("Cor2 3333333333333333");
yield return StartCoroutine(Cor1());
Debug.Log("Cor2 4444444444444444");
}
使用 Lua 模擬:
主要邏輯:使用計算第一個協程(cor1)執行的時間,使第二個協程需要後執行的邏輯也等相同或者相同多一點的時間之後,再執行代碼如下:
function CorTest()
local cor1 = coroutine.create(function()
print("cor1 1111111111111111");
WaitForSeconds(2);
print("cor1 2222222222222222");
end);
local cor2 = coroutine.create(function()
print("cor2 3333333333333333");
--開啓cor1的邏輯
coroutine.resume(cor1);
-- 等cor1要執行的時間
WaitForSeconds(2);
-- 多等1幀
WaitForFixedUpdate();
print("cor2 4444444444444444");
end);
coroutine.resume(cor2);
end
缺陷:有可能因爲顯示卡頓或者邏輯複雜,導致雖然都是相同的等待時間cor2需要後執行的邏輯卻先執行了。
改善版本,邏輯:判斷 cor1 的狀態來確定 cor2 後面的邏輯是否繼續執行;
function CorTest()
local cor1 = coroutine.create(function()
print("cor1 1111111111111111");
WaitForSeconds(2);
print("cor1 2222222222222222");
end);
local cor2 = coroutine.create(function()
print("cor2 3333333333333333");
--開啓cor1的邏輯
coroutine.resume(cor1);
--print("看下cor1當前狀態",coroutine.status(cor1))
while true do
WaitForFixedUpdate();
if coroutine.status(cor1) == "dead" then
break;
end
end
print("cor2 4444444444444444");
end);
coroutine.resume(cor2);
end
擴展:使用StopCoroutine(Cor1());的問題:
代碼如下這樣寫是不能停止掉Cor1的,
void CorTest()
{
// 使用字符串爲參數的調用是沒有問題的
StartCoroutine("Cor1");
StopCoroutine("Cor1");
// 錯誤的停止協程的方法
StartCoroutine(Cor1());
StopCoroutine(Cor1());
}
StopCoroutine的官方註釋譯文:停止名爲methodName的第一個協同程序,或存儲在例程中的協同程序運行此行爲。
// 摘要:
// Stops the first coroutine named methodName, or the coroutine stored in routine
// running on this behaviour.
//
// 參數:
// methodName:
// Name of coroutine.
//
// routine:
// Name of the function in code.
public void StopCoroutine(IEnumerator routine);
我個人理解爲StartCoroutine(Cor1()); 和 StopCoroutine(Cor1()); 這兩個Cor1 它認爲不是一個(不知道對不對啊);
看下能成功停止調用的方法吧:
private void OnEnable()
{
// 正確的操作:
Coroutine cor = StartCoroutine(Cor1());
StopCoroutine(cor);
// 或者這樣:
IEnumerator cor1 = Cor1();
StartCoroutine(cor1);
StopCoroutine(cor1);
}