天天看點

Lua腳本怎麼樣調用外部腳本?

    在遊戲腳本開發中,我們往往會發現腳本量非常大,而且我們經常會在一些核心腳本檔案中定義常用的功能函數,但是Lua腳本沒有提供include關鍵詞,那又是怎樣調用外部函數的呢?如何實作腳本的Include功能?

test.lua腳本定義main函數如下:

function main(szName, num1, num2)   
    print("main()", szName, num1, num2);
    local nRandMax = 10000; 
    local nRand = math.random(nRandMax);    
    print("nRand =", nRand)
    return 1;
end      

現在我想在test.lua腳本中調用另外一個test1.lua腳本檔案中的GetRandMax(),通常的做法是這樣的:

function main(szName, num1, num2)   
    print("main()", szName, num1, num2);
    dofile("test1.lua")     --加載并編譯運作腳本
    local nRandMax = GetRandMax();  
    local nRand = math.random(nRandMax);    
    print("nRand =", nRand)
    return 1;
end      

看上去是這樣的,非常簡單,通過dofile對test1.lua檔案進行加載并編譯運作,這部操作會将test1.lua檔案中的函數和變量壓入全局的虛拟棧中,這樣就可以實作對GetRandMax()調用。但是這裡有個問題:dofile函數接受的是需要引用的外部腳本的路徑,如果多次調用會不勝其煩,而且效率不高。可能有人誰說,那我們直接把dofile作為全局函數執行,就像這樣:

dofile("test1.lua")
dofile("test2.lua") 
dofile("test3.lua") 

function main(szName, num1, num2)   
    print("main()", szName, num1, num2);
    local nRandMax = GetRandMax();  --調用test1.lua中的函數
    local nRand = math.random(nRandMax);    
    print("nRand =", nRand)
    return 1;
end      

這樣做是可以的,但是仍然有些問題:

    1,如果test.lua檔案dofile(test1.lua),而test1.lua檔案dofile(test.lua),怎麼辦!出現循環應用,執行後堆棧溢出;

test.lua:5: too many C levels (limit is 200) in function at line 5 near '"main()"'      

    2,dofile的路徑問題,每次都要傳入檔案的絕對路徑,如果路徑不正确,無法正常執行,這也是個很煩的事。

cannot open \script\test.lua: No such file or directory      

那怎樣做才更好呢?既然dofile有這些的問題,我們就把這些問題解決。在C/C++中實作Include腳本接口函數,在腳本中作為全局函數調用,實作外部腳本檔案包含功能。

//腳本接口
TLua_Funcs g_GameFunc[] = {
  { "Include",        LuaInclude },
  { "ReloadAllScript",    LuaReloadAllScript},
  { "SayHello",       LuaSayHello },
  { "StopGame",       LuaStopGame },
};      

在Include函數中使用set集合避免重複包含的問題,擷取目前的執行路徑拼接成絕對路徑,這樣就省了不少事;)

Include("\\script\\test1.lua") --Include腳本接口

function main(szName, num1, num2)   
    print("main()", szName, num1, num2);
    local nRandMax = GetRandMax();  --調用test1.lua中的函數
    local nRand = math.random(nRandMax);    
    print("nRand =", nRand)
    return 1;
end      

繼續閱讀