跳至主要内容

Lua 腳本:疑難排解

本頁介紹撰寫或除錯 FreeMinecraftModels 道具腳本時可能遇到的常見問題,以及使用延遲設定產生系統的技巧。如果您正在尋找可運行的範例,請參閱範例與模式。如果您剛入門,請參閱入門指南


常見問題

1. 設定檔未載入 / 腳本未關聯

症狀: 道具已生成,但不回應點擊或任何鉤子。

原因和解決方法:

  • 尚不存在 .yml 設定檔。 FMM 在道具首次生成時延遲建立設定。首次生成模型時,FMM 會非同步建立帶有預設值(已啟用、無腳本)的 .yml 設定。您需要編輯產生的設定以新增腳本檔名,然後重新生成道具。

  • 設定中設定了 isEnabled: false 開啟模型檔案旁邊的 .yml 檔案,將其設定為 isEnabled: true

  • scripts: 列表為空。 新增您的腳本檔名:

    isEnabled: true
    scripts:
    - my_script.lua
  • .yml 檔名與模型檔名不符。 設定必須與模型檔案具有相同的基本名稱。例如,torch_01.fmmodel 需要同一目錄下的 torch_01.yml


2. 找不到腳本檔案

症狀: 主控台顯示:[FMM Scripts] Script 'my_script.lua' not found in scripts/ folder

原因和解決方法:

  • 目錄錯誤。 腳本檔案必須位於 plugins/FreeMinecraftModels/scripts/,而不是模型檔案旁邊。

  • 檔名不符。 .yml 設定中的名稱必須與 scripts/ 資料夾中的檔名完全相符,包括大小寫和 .lua 副檔名。

  • 檔案不存在。 請仔細檢查 .lua 檔案是否確實存在於 scripts/ 資料夾中。


3. 腳本完全無法載入

症狀: 沒有主控台錯誤,但沒有鉤子觸發。

檢查伺服器主控台在啟動時是否有 Lua 語法錯誤。最常見的原因是:

  • 缺少 end 來關閉函式或 if 區塊
  • 括號不配對
  • 回傳的表中鉤子定義之間缺少逗號
  • 檔案不以 .lua 結尾

如果存在 Lua 錯誤,主控台會輸出一個 [Lua] 錯誤區塊,包含檔名、行號和描述。


4. 鉤子從未觸發

症狀: 腳本已載入(您看到了 [FMM Scripts] Bound script 訊息),但特定的鉤子從未觸發。

驗證鉤子名稱是否與鉤子參考中列出的完全一致。常見錯誤:

錯誤名稱正確名稱
on_clickon_right_clickon_left_click
on_interacton_right_click
on_hiton_left_click
on_tickon_game_tick
on_removeon_destroy
on_arrow_hiton_projectile_hit

還要驗證道具是否確實有關聯的盔甲架實體。某些道具設定可能不會產生可點擊的實體。


5. 逾時 / 超出執行預算

症狀: 主控台顯示如下訊息:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

腳本在單次鉤子呼叫中執行了過多的工作。常見原因:

  • on_game_tick 中遍歷了過多的實體
  • 每 tick 建立了過多的粒子效果
  • 在沒有將工作分散到多個 tick 的情況下執行了高開銷的迴圈

解決方法: 將繁重的工作放到基於狀態的冷卻時間之後,或者使用 scheduler:run_repeating() 搭配合理的間隔來取代 on_game_tick


6. 點擊鉤子中 context.event 為 nil

這在 on_left_clickon_right_click 中通常不應該發生,但始終使用以下方式進行保護:

if context.event then
context.event.cancel()
end

在排程器回呼內部,context.event 始終為 nil——這是預期行為。事件修改只能在事件鉤子本身內部進行。


7. 動畫不播放

症狀: play_animation() 回傳 false,或者沒有可見的變化。

原因和解決方法:

  • 動畫名稱錯誤。 名稱必須與模型檔案中定義的完全相符。檢查您的 .bbmodel.fmmodel 檔案以取得正確的動畫名稱。

  • 模型沒有動畫。 並非所有模型都有動畫。驗證模型檔案是否確實包含動畫資料。

  • 玩家不在資源包範圍內。 動畫在伺服器端執行,但玩家需要載入 FMM 資源包才能看到模型。


8. 粒子不出現

  • 驗證粒子名稱是有效的 Bukkit Particle 列舉值且為大寫:"FLAME",而不是 "flame"
  • 驗證位置位於已載入的區塊中。如果附近沒有玩家,區塊可能已卸載。
  • 驗證 count 至少為 1。
  • 某些粒子(如 DUST)需要特定的額外資料,基本的 spawn_particle() 可能不支援。使用標準粒子如 FLAMEHEARTHAPPY_VILLAGERNOTEENCHANT 等。

9. 聲音不播放

  • 驗證聲音名稱是有效的 Bukkit Sound 列舉常數且為大寫。範例:"BLOCK_NOTE_BLOCK_HARP",而不是 "block.note_block.harp"
  • 驗證位置座標是否正確(不全為零或 NaN)。
  • 驗證音量大於 0。

10. 狀態意外重置

context.state 是按道具實例存在的,並在道具的生命週期內持續存在。如果狀態似乎被重置了:

  • 道具可能已被移除並重新生成(每次生成都會建立新實例)。
  • 您可能在排程器回呼中使用了錯誤的上下文變數來讀取狀態。始終使用回呼自身的上下文參數。

延遲設定產生的工作原理

了解延遲設定系統有助於避免設定新道具時的困惑:

  1. 首次生成: 當道具生成且不存在相鄰的 .yml 檔案時,FMM 非同步建立設定。這意味著檔案在背景執行緒中寫入,不會立即可用。

  2. 預設值: 產生的設定包含 isEnabled: true 和空的 scripts: [] 列表。

  3. 首次生成時沒有腳本: 由於設定是在道具已經生成之後建立的(且沒有列出腳本),道具在首次生成時不會關聯任何腳本。

  4. 編輯並重新生成: FMM 建立設定後,您編輯它以新增腳本檔名。下次道具生成時,腳本將被載入。

  5. 設定位置: .yml 檔案建立在與模型檔案相同的目錄中,具有相同的基本名稱。例如:

    • 模型:plugins/FreeMinecraftModels/models/fountain.fmmodel
    • 設定:plugins/FreeMinecraftModels/models/fountain.yml
快速設定流程
  1. 將模型放入 models/
  2. 將腳本放入 scripts/
  3. 生成道具一次(產生 .yml
  4. 編輯 .yml 新增 scripts: [my_script.lua]
  5. 重新生成道具——腳本現在已啟用

閱讀錯誤訊息

當 Lua 道具腳本出錯時,主控台會輸出一個 [Lua] 錯誤區塊。這些訊息會用淺顯易懂的語言準確地告訴您哪個檔案、哪一行、哪個鉤子以及出了什麼問題。

典型的錯誤如下所示:

[Lua] Error in 'my_door.lua' at line 12 during 'on_right_click':
[Lua] -> You tried to call a method or function that doesn't exist.
[Lua] -> Check the method name for typos, or make sure you're using ':' (colon) for method calls, not '.' (dot).
[Lua] -> Script has been disabled for this entity to prevent further errors.

系統將常見的 Lua 錯誤翻譯為淺顯易懂的語言:

原始 Lua 錯誤主控台告訴您的內容
attempt to call nil您嘗試呼叫一個不存在的方法或函式。檢查拼寫錯誤和 :. 的用法。
index expected, got nil您嘗試存取一個 nil 物件的欄位。檢查之前的程式碼是否已初始化它。
attempt to index您嘗試存取一個 nil 或無效值的屬性。
bad argument函式接收了錯誤類型的引數。訊息顯示了期望的類型與實際類型。
Timeout您的腳本在 'hook_name' 中耗時 Xms(限制:50ms)——腳本已被停用以防止延遲。
提示

在深入程式碼之前,請始終閱讀完整的 [Lua] 錯誤訊息。它通常會直接指向解決方法。


不要假設存在未文件化的方法

FMM Lua API 公開了一組特定的方法。不要假設存在簡寫名稱或替代名稱。常見錯誤:

  • context.prop:get_location() ——不存在。使用 context.prop.current_location(欄位,不是方法)。
  • context.prop:set_animation("open") ——不存在。使用 context.prop:play_animation("open", true, true)
  • context.event:setCancelled(true) ——不存在。使用 context.event.cancel()
  • context.cooldowns:check_local(...) ——在 FMM 中不存在。使用 context.state 搭配 scheduler:run_later() 實現冷卻。
  • context.player ——在 FMM 道具腳本中不存在。使用 context.world:get_nearby_players() 尋找道具附近的玩家。
  • context.boss ——不存在。那是 EliteMobs 的。在 FMM 中使用 context.prop

如有疑問,請查看道具 API 頁面。如果那裡沒有文件記錄,則表示不存在。


除錯技巧

1. 大量使用 context.log:info()

除錯時在每個步驟新增日誌訊息:

on_right_click = function(context)
context.log:info("Right click received!")
context.log:info("Event present: " .. tostring(context.event ~= nil))
context.log:info("State is_open: " .. tostring(context.state.is_open))
end

2. 在啟動時檢查主控台

FMM 會為每次成功繫結記錄 [FMM Scripts] Bound script 'X' to prop 'Y'。如果您沒有看到此訊息,則設定或腳本未被載入。

3. 驗證模型檔案路徑

.yml 設定必須是模型檔案的同層檔案(相同目錄、相同基本名稱)。透過檢查以下內容來驗證:

  • 模型檔案路徑:plugins/FreeMinecraftModels/models/my_model.fmmodel
  • 設定檔案路徑:plugins/FreeMinecraftModels/models/my_model.yml

4. 單獨測試鉤子

建構複雜腳本時,先單獨測試每個鉤子。一次新增一個鉤子,驗證其觸發後再新增下一個。

5. 檢查鉤子名稱的拼寫錯誤

鉤子不觸發的最常見原因是鉤子名稱拼寫錯誤。腳本會無錯載入,但拼寫錯誤的鉤子函式會在驗證時被拒絕。


初學者學習路徑

如果您想從零開始學習此系統,以下學習路徑效果很好:

  1. 撰寫一個只包含 api_version = 1 和記錄訊息的 on_spawn 的檔案。
  2. 將腳本新增到道具設定中,驗證日誌訊息是否出現。
  3. 新增 on_right_click 並在道具被點擊時記錄日誌。
  4. 新增 on_left_click 搭配 context.event.cancel() 實現無敵。
  5. 在右鍵點擊時播放動畫。
  6. 在右鍵點擊時新增聲音。
  7. 新增狀態和切換行為。
  8. 新增區域監視以實現近距離偵測。
  9. 此後才開始撰寫帶有排程器的複雜多鉤子腳本。

每個步驟都建立在前一步的基礎上,您可以在每個階段進行測試。


下一步