LuaState.cs
其中的OpenBaseLuaLibs()
public void Start()
{
#if UNITY_EDITOR
beStart = true;
#endif
Debugger.Log("LuaState start");
OpenBaseLuaLibs();
#if ENABLE_LUA_INJECTION
Push(LuaDLL.tolua_tag());
LuaSetGlobal("tolua_tag");
#if UNITY_EDITOR
if (UnityEditor.EditorPrefs.GetInt(Application.dataPath + "InjectStatus") == 1)
{
#endif
DoFile("System/Injection/LuaInjectionStation.lua");
bInjectionInited = true;
#if UNITY_EDITOR
}
#endif
#endif
PackBounds = GetFuncRef("Bounds.New");
UnpackBounds = GetFuncRef("Bounds.Get");
PackRay = GetFuncRef("Ray.New");
UnpackRay = GetFuncRef("Ray.Get");
PackRaycastHit = GetFuncRef("RaycastHit.New");
PackTouch = GetFuncRef("Touch.New");
}
void OpenBaseLuaLibs()
{
DoFile("tolua.lua"); //tolua table名字已经存在了,不能用require
LuaUnityLibs.OpenLuaLibs(L);
}
LuaUnityLibs.cs
其中的LuaDLL.tolua_openlualibs()
public static void OpenLuaLibs(IntPtr L)
{
if (LuaDLL.tolua_openlualibs(L) != 0)
{
string error = LuaDLL.lua_tostring(L, -1);
LuaDLL.lua_pop(L, 1);
throw new LuaException(error);
}
SetOutMethods(L, "Vector3", GetOutVector3);
SetOutMethods(L, "Vector2", GetOutVector2);
SetOutMethods(L, "Vector4", GetOutVector4);
SetOutMethods(L, "Color", GetOutColor);
SetOutMethods(L, "Quaternion", GetOutQuaternion);
SetOutMethods(L, "Ray", GetOutRay);
SetOutMethods(L, "Bounds", GetOutBounds);
SetOutMethods(L, "Touch", GetOutTouch);
SetOutMethods(L, "RaycastHit", GetOutRaycastHit);
SetOutMethods(L, "LayerMask", GetOutLayerMask);
}
tolua.c
static int _openlualibs(lua_State *L)
{
tolua_openvaluetype(L);
tolua_openluavec3(L);
tolua_openluavec2(L);
tolua_openluavec4(L);
tolua_openluaclr(L);
tolua_openluaquat(L);
tolua_openlualayermask(L);
tolua_openupdate(L);
return 0;
}
LUALIB_API int tolua_openlualibs(lua_State *L)
{
lua_pushcfunction(L, _openlualibs);
return lua_pcall(L, 0, -1, 0);
}
void tolua_openupdate(lua_State *L)
{
lua_getglobal(L, "Update");
if (!lua_isfunction(L, 1))
{
luaL_error(L, "Update function does not exist or not be loaded");
return;
}
//我们使用伪索引LUA_REGISTRYINDEX来取得lua的注册表,然后在注册表中添加成员
//Register[LUA_RIDX_UPDATE] = Update,这个Update是在event.lua中
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_UPDATE);
lua_getglobal(L, "LateUpdate");
if (!lua_isfunction(L, 1))
{
luaL_error(L, "LateUpdate function does not exist or not be loaded");
return;
}
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_LATEUPDATE);
lua_getglobal(L, "FixedUpdate");
if (!lua_isfunction(L, 1))
{
luaL_error(L, "FixedUpdate function does not exist or not be loaded");
return;
}
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_FIXEDUPDATE);
}
event.lua
function event(name, safe)
safe = safe or false
return setmetatable({name = name, keepSafe = safe, lock = false, opList = {}, list = list:new()}, _event)
end
UpdateBeat = event("Update", true)
LateUpdateBeat = event("LateUpdate", true)
FixedUpdateBeat = event("FixedUpdate", true)
CoUpdateBeat = event("CoUpdate") --只在协同使用
local Time = Time
local UpdateBeat = UpdateBeat
local LateUpdateBeat = LateUpdateBeat
local FixedUpdateBeat = FixedUpdateBeat
local CoUpdateBeat = CoUpdateBeat
--逻辑update
function Update(deltaTime, unscaledDeltaTime)
Time:SetDeltaTime(deltaTime, unscaledDeltaTime)
UpdateBeat()
end
function LateUpdate()
LateUpdateBeat()
CoUpdateBeat()
Time:SetFrameCount()
end
--物理update
function FixedUpdate(fixedDeltaTime)
Time:SetFixedDelta(fixedDeltaTime)
FixedUpdateBeat()
end
function PrintEvents()
UpdateBeat:Dump()
FixedUpdateBeat:Dump()
end
由上面的流程我们知道,我们最终将event.lua中的update函数我们放置到了lua中的注册表Registry[LUA_RIDX_UPDATE]中,等待被访问
LuaLooper.cs
由unity的Update()来触发每次的调用
void Update()
{
#if UNITY_EDITOR
if (luaState == null)
{
return;
}
#endif
if (luaState.LuaUpdate(Time.deltaTime, Time.unscaledDeltaTime) != 0)
{
ThrowException();
}
luaState.LuaPop(1);
luaState.Collect();
#if UNITY_EDITOR
luaState.CheckTop();
#endif
}
LuaState.cs
public int LuaUpdate(float delta, float unscaled)
{
return LuaDLL.tolua_update(L, delta, unscaled);
}
tolua.c
//这里获取了在注册表中的Update函数,然后传入了两个参数,最后调用该函数
LUALIB_API int tolua_update(lua_State *L, float deltaTime, float unscaledTime)
{
int top = tolua_beginpcall(L, LUA_RIDX_UPDATE);
lua_pushnumber(L, deltaTime);
lua_pushnumber(L, unscaledTime);
return lua_pcall(L, 2, -1, top);
}
LUALIB_API int tolua_beginpcall(lua_State *L, int reference)
{
lua_getref(L, LUA_RIDX_CUSTOMTRACEBACK);
int top = lua_gettop(L);
lua_getref(L, reference);
return top;
}