通过 util.cs_generator 可以用一个 function 模拟一个IEnumerator,在里头用coroutine.yield,就类似C#里头的yield return。

Lua对接C#协程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local util = require 'xlua.util'

local gameobject = CS.UnityEngine.GameObject('Coroutine_Runner') --创建一个空物体,为协程运行器(下面源码分析)
CS.UnityEngine.Object.DontDestroyOnLoad(gameobject) --设置加载时不销毁
local cs_coroutine_runner =
gameobject:AddComponent(typeof(CS.XLuaTest.Coroutine_Runner)) --添加 Coroutine_Runner C#脚本

return
{
--启动 协程运行器的一个协程
start = function(...)
return cs_coroutine_runner:StartCoroutine(util.cs_generator(...)) --生成迭代器(下面源码解析)
end;
--停止 协程运行器的一个协程
stop = function(coroutine)
cs_coroutine_runner:StopCoroutine(coroutine)
end
}

util.cs_generator(…) 源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
local function cs_generator(func, ...)
local params = {...}
local generator = setmetatable
({
w_func = function()
func(unpack(params)) --使用table.unpack(table,si,ei) 将表拆开为参数列表形式
return move_end
end
},
generator_mt
)
generator:Reset() --迭代器重置,返回一个协程函数并设置到generator表的co字段
return generator -- 返回生成的迭代器
end

local generator_mt = {
__index = {
MoveNext = function(self)
self.Current = self.co()
if self.Current == move_end then
self.Current = nil
return false
else
return true
end
end;
Reset = function(self)
self.co = coroutine.wrap(self.w_func) --创建协程,并返回协程函数,协程函数调用就启动协程
end
}
}

Coroutine_Runner 源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using UnityEngine;
using XLua;
using System.Collections.Generic;
using System;

namespace XLuaTest
{
//用来运行unity协程的的MonoBehaviour
public class Coroutine_Runner : MonoBehaviour
{
}

//XLua配置
public static class CoroutineConfig
{
//动态列表配置方式,使用静态属性返回一个Type类型的列表
[LuaCallCSharp]
public static List<Type> LuaCallCSharp
{
get
{
return new List<Type>()
{
typeof(WaitForSeconds), //要生成代码的类型
typeof(WWW)
};
}
}
}
}

Lua 使用C#协程

1
2
3
4
5
6
7
8
9
10
cs_coroutine.start
( function()
print('start coroutine')

print('start wait 5s')
coroutine.yield(CS.UnityEngine.WaitForSeconds(5))
print('wait 5s down')

end
)