291 lines
8.3 KiB
C#
291 lines
8.3 KiB
C#
|
/*
|
|||
|
Copyright (c) 2015-2017 topameng(topameng@qq.com)
|
|||
|
|
|||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
of this software and associated documentation files (the "Software"), to deal
|
|||
|
in the Software without restriction, including without limitation the rights
|
|||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
|
copies of the Software, and to permit persons to whom the Software is
|
|||
|
furnished to do so, subject to the following conditions:
|
|||
|
|
|||
|
The above copyright notice and this permission notice shall be included in all
|
|||
|
copies or substantial portions of the Software.
|
|||
|
|
|||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
|
SOFTWARE.
|
|||
|
*/
|
|||
|
using UnityEngine;
|
|||
|
using LuaInterface;
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
|
|||
|
public static class LuaCoroutine
|
|||
|
{
|
|||
|
private static MonoBehaviour mb = null;
|
|||
|
private static string strCo =
|
|||
|
@"
|
|||
|
local _WaitForSeconds, _WaitForFixedUpdate, _WaitForEndOfFrame, _Yield, _StopCoroutine = WaitForSeconds, WaitForFixedUpdate, WaitForEndOfFrame, Yield, StopCoroutine
|
|||
|
local error = error
|
|||
|
local debug = debug
|
|||
|
local coroutine = coroutine
|
|||
|
local comap = {}
|
|||
|
setmetatable(comap, {__mode = 'k'})
|
|||
|
|
|||
|
function _resume(co)
|
|||
|
if comap[co] then
|
|||
|
comap[co] = nil
|
|||
|
local flag, msg = coroutine.resume(co)
|
|||
|
|
|||
|
if not flag then
|
|||
|
msg = debug.traceback(co, msg)
|
|||
|
error(msg)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function WaitForSeconds(t)
|
|||
|
local co = coroutine.running()
|
|||
|
local resume = function()
|
|||
|
_resume(co)
|
|||
|
end
|
|||
|
|
|||
|
comap[co] = _WaitForSeconds(t, resume)
|
|||
|
return coroutine.yield()
|
|||
|
end
|
|||
|
|
|||
|
function WaitForFixedUpdate()
|
|||
|
local co = coroutine.running()
|
|||
|
local resume = function()
|
|||
|
_resume(co)
|
|||
|
end
|
|||
|
|
|||
|
comap[co] = _WaitForFixedUpdate(resume)
|
|||
|
return coroutine.yield()
|
|||
|
end
|
|||
|
|
|||
|
function WaitForEndOfFrame()
|
|||
|
local co = coroutine.running()
|
|||
|
local resume = function()
|
|||
|
_resume(co)
|
|||
|
end
|
|||
|
|
|||
|
comap[co] = _WaitForEndOfFrame(resume)
|
|||
|
return coroutine.yield()
|
|||
|
end
|
|||
|
|
|||
|
function Yield(o)
|
|||
|
local co = coroutine.running()
|
|||
|
local resume = function()
|
|||
|
_resume(co)
|
|||
|
end
|
|||
|
|
|||
|
comap[co] = _Yield(o, resume)
|
|||
|
return coroutine.yield()
|
|||
|
end
|
|||
|
|
|||
|
function StartCoroutine(func)
|
|||
|
local co = coroutine.create(func)
|
|||
|
local flag, msg = coroutine.resume(co)
|
|||
|
|
|||
|
if not flag then
|
|||
|
msg = debug.traceback(co, msg)
|
|||
|
error(msg)
|
|||
|
end
|
|||
|
|
|||
|
return co
|
|||
|
end
|
|||
|
|
|||
|
function StopCoroutine(co)
|
|||
|
local _co = comap[co]
|
|||
|
|
|||
|
if _co == nil then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
comap[co] = nil
|
|||
|
_StopCoroutine(_co)
|
|||
|
end
|
|||
|
";
|
|||
|
|
|||
|
public static void Register(LuaState state, MonoBehaviour behaviour)
|
|||
|
{
|
|||
|
state.BeginModule(null);
|
|||
|
state.RegFunction("WaitForSeconds", _WaitForSeconds);
|
|||
|
state.RegFunction("WaitForFixedUpdate", WaitForFixedUpdate);
|
|||
|
state.RegFunction("WaitForEndOfFrame", WaitForEndOfFrame);
|
|||
|
state.RegFunction("Yield", Yield);
|
|||
|
state.RegFunction("StopCoroutine", StopCoroutine);
|
|||
|
state.RegFunction("WrapLuaCoroutine", WrapLuaCoroutine);
|
|||
|
state.EndModule();
|
|||
|
|
|||
|
state.LuaDoString(strCo, "LuaCoroutine.cs");
|
|||
|
mb = behaviour;
|
|||
|
}
|
|||
|
|
|||
|
//另一种方式,非脚本回调方式(用脚本方式更好,可避免lua_yield异常出现在c#函数中)
|
|||
|
/*[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
static int WaitForSeconds(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
LuaState state = LuaState.Get(L);
|
|||
|
LuaDLL.lua_pushthread(L);
|
|||
|
LuaThread thread = ToLua.ToLuaThread(L, -1);
|
|||
|
float sec = (float)LuaDLL.luaL_checknumber(L, 1);
|
|||
|
mb.StartCoroutine(CoWaitForSeconds(sec, thread));
|
|||
|
return LuaDLL.lua_yield(L, 0);
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static IEnumerator CoWaitForSeconds(float sec, LuaThread thread)
|
|||
|
{
|
|||
|
yield return new WaitForSeconds(sec);
|
|||
|
thread.Resume();
|
|||
|
}*/
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int _WaitForSeconds(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
float sec = (float)LuaDLL.luaL_checknumber(L, 1);
|
|||
|
LuaFunction func = ToLua.ToLuaFunction(L, 2);
|
|||
|
Coroutine co = mb.StartCoroutine(CoWaitForSeconds(sec, func));
|
|||
|
ToLua.PushSealed(L, co);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static IEnumerator CoWaitForSeconds(float sec, LuaFunction func)
|
|||
|
{
|
|||
|
yield return new WaitForSeconds(sec);
|
|||
|
func.Call();
|
|||
|
}
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int WaitForFixedUpdate(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
LuaFunction func = ToLua.ToLuaFunction(L, 1);
|
|||
|
Coroutine co = mb.StartCoroutine(CoWaitForFixedUpdate(func));
|
|||
|
ToLua.PushSealed(L, co);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static IEnumerator CoWaitForFixedUpdate(LuaFunction func)
|
|||
|
{
|
|||
|
yield return new WaitForFixedUpdate();
|
|||
|
func.Call();
|
|||
|
}
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int WaitForEndOfFrame(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
LuaFunction func = ToLua.ToLuaFunction(L, 1);
|
|||
|
Coroutine co = mb.StartCoroutine(CoWaitForEndOfFrame(func));
|
|||
|
ToLua.PushSealed(L, co);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static IEnumerator CoWaitForEndOfFrame(LuaFunction func)
|
|||
|
{
|
|||
|
yield return new WaitForEndOfFrame();
|
|||
|
func.Call();
|
|||
|
}
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int Yield(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
object o = ToLua.ToVarObject(L, 1);
|
|||
|
LuaFunction func = ToLua.ToLuaFunction(L, 2);
|
|||
|
Coroutine co = mb.StartCoroutine(CoYield(o, func));
|
|||
|
ToLua.PushSealed(L, co);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static IEnumerator CoYield(object o, LuaFunction func)
|
|||
|
{
|
|||
|
if (o is IEnumerator)
|
|||
|
{
|
|||
|
yield return mb.StartCoroutine((IEnumerator)o);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
yield return o;
|
|||
|
}
|
|||
|
|
|||
|
func.Call();
|
|||
|
}
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int StopCoroutine(IntPtr L)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Coroutine co = (Coroutine)ToLua.CheckObject(L, 1, typeof(Coroutine));
|
|||
|
mb.StopCoroutine(co);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
return LuaDLL.toluaL_exception(L, e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
|
|||
|
private static int WrapLuaCoroutine(IntPtr L)
|
|||
|
{
|
|||
|
LuaFunction func = ToLua.ToLuaFunction(L, 1);
|
|||
|
IEnumerator enumerator = CoWrap(func);
|
|||
|
ToLua.Push(L, enumerator);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
private static IEnumerator CoWrap(LuaFunction func)
|
|||
|
{
|
|||
|
if (func == null)
|
|||
|
{
|
|||
|
yield break;
|
|||
|
}
|
|||
|
|
|||
|
while (func.Invoke<bool>())
|
|||
|
{
|
|||
|
yield return null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|