跳轉到內容

SpringRTS/Gadgets 中的 Lua

來自華夏公益教科書,面向開放世界的開放書籍

Gadgets 是指令碼檔案,必須由所有玩家提供。這就是為什麼 Gadgets 在模組和地圖中使用的原因,因為它們應該始終具有完全相同的資料。Gadgets 可以從同步和非同步模式中使用呼叫和回撥,但你需要一種特殊的方法來讓同步和非同步程式碼相互通訊。

製作 Gadget 時,始終將同步程式碼與非同步程式碼分開。可以使用以下方法實現:

if (gadgetHandler:IsSyncedCode()) then
           --  Synced code here --
else
           -- Unsynced code here --
end


這樣可以確保程式碼塊位於正確的位置。不使用 gadgetHandler:IsSyncedCode() 將導致程式碼在同步和非同步模式下都執行。這種情況在很多情況下會導致錯誤,因此不建議這樣做。請指定程式碼是在同步模式下使用還是非同步模式下使用。
製作 Gadget 時,始終將遊戲事件(UnitCreated()、UnitDestroyed() 等)放置在同步程式碼塊中,而僅與 Lua 圖形相關的事件應放置在非同步程式碼塊中。
確定某項操作是否應該放置在非同步程式碼或同步程式碼中的一種簡單方法是,判斷程式碼是否應該對所有使用者產生相同的效果,還是隻對您產生效果。Lua 圖形放置在非同步程式碼中的原因是,即使一名使用者沒有獲得正確的圖形,也不意味著其他玩家也會遇到相同的問題。因此,這樣做可以使遊戲流程順暢。例如,如果 UnitDestroyed() 位於非同步程式碼中,那麼電腦較慢的玩家可能會延遲收到事件,從而導致遊戲不可玩,因為他的事件會延遲。

同步/非同步通訊

[編輯 | 編輯原始碼]

使用全域性變數

[編輯 | 編輯原始碼]

在同步和非同步程式碼之間通訊的一種方法是使用全域性變數。我們使用 Lua 中的 _G 表將變數新增為全域性變數

_G.variable=variable --we assign variable to the global table


下面演示了透過全域性變數進行同步/非同步通訊

--SYNCED CODE
if (gadgetHandler:IsSyncedCode()) then
   local number = 10                        -- declaring local variable 'number'
   function gadget:SomeSyncedCallin(...)
      number=number+1                       -- increment variable's value by one
      _G.number=number                      -- save the new value into a global variable
   end
else

--UNSYNCED CODE
   function gadget:Update(...)              -- here goes some unsynced callin. we use Update to see the result in real time
      Spring.Echo(SYNCED.number)            -- print the global variable's value on screen
   end
end

在示例中,我們在同步程式碼部分聲明瞭一個區域性變數,並在同步模式下嘗試更改它的值。然後,我們將該值儲存為全域性變數。之後,如果我們想在非同步程式碼中讀取該值,只需使用 "SYNCED." 表即可。

使用 SendToUnsynced() 函式

[編輯 | 編輯原始碼]

第二種方法是使用 SendToUnsynced() 函式。

華夏公益教科書