using UnityEngine;
using System.Collections;
using LuaInterface;
public class TestLuaThread : MonoBehaviour // lua的coroutine映射到C#中tolua的封装成luathread对象,resume来控制Lua中线程的运行
{
string script =
@"
function fib(n)
local a, b = 0, 1
while n > 0 do
a, b = b, a + b
n = n - 1
end
return a
end
function CoFunc(len)
print('Coroutine started')
local i = 0
for i = 0, len, 1 do
local flag = coroutine.yield(fib(i)) --等待resume,返回值就是fib(i)
if not flag then
print('Coroutine not flag')
break
end
end
print('Coroutine ended')
end
function Test()
local co = coroutine.create(CoFunc)
return co
end
";
LuaState state = null;
LuaThread thread = null;
string tips = null;
void Start ()
{
#if UNITY_5 || UNITY_2017 || UNITY_2018
Application.logMessageReceived += ShowTips;
#else
Application.RegisterLogCallback(ShowTips);
#endif
new LuaResLoader();
state = new LuaState();
state.Start();
state.LogGC = true;
state.DoString(script);
LuaFunction func = state.GetFunction("Test");
func.BeginPCall();
func.PCall(); //创建线程
thread = func.CheckLuaThread(); //获取LuaThread
thread.name = "LuaThread";
func.EndPCall();
func.Dispose();
func = null;
thread.Resume(10); //第一次resume,参数10
}
void OnApplicationQuit()
{
if (thread != null)
{
thread.Dispose();
thread = null;
}
state.Dispose();
state = null;
#if UNITY_5 || UNITY_2017 || UNITY_2018
Application.logMessageReceived -= ShowTips;
#else
Application.RegisterLogCallback(null);
#endif
}
void ShowTips(string msg, string stackTrace, LogType type)
{
tips += msg;
tips += "\r\n";
}
void Update()
{
state.CheckTop();
state.Collect();
}
void OnGUI()
{
GUI.Label(new Rect(Screen.width / 2 - 300, Screen.height / 2 - 200, 600, 400), tips);
if (GUI.Button(new Rect(10, 50, 120, 40), "Resume Thead"))
{
int ret = -1;
if (thread != null && thread.Resume(true, out ret) == (int)LuaThreadStatus.LUA_YIELD)
{
Debugger.Log("lua yield: " + ret);
}
}
else if (GUI.Button(new Rect(10, 150, 120, 40), "Close Thread"))
{
if (thread != null)
{
thread.Dispose();
thread = null;
}
}
}
}
在执行到yield之后,代码跳转到上一次resume代码的后一条代码执行
再次调用resume,代码就跳转到上一次yield代码的后一条代码执行。
一般来说,resume方法在主线程中调用;而yield则是在coroutine内调用,包括coroutine内部调用的函数内部。
当然了,在coroutine中调用resume没有什么问题,但这样是没有什么意义的,因为如果代码还在coroutine中执行的话,则说明其状态一定是running的,这个时候的resume是没有任何意义的。而在主线程中调用yield,会导致 “lua: attempt to yield across metamethod/C-call boundary”的错误。
Stop的情况:
Resume完毕的情况:
Lualooper的update里面会有:
luaState.Collect();
#if UNITY_EDITOR
luaState.CheckTop();
#endif
所以c#的update因为没有用lualooper就要手动checktop()和collect() ?