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設定内の名前は、大文字小文字と.lua拡張子を含め、scripts/フォルダ内のファイル名と正確に一致する必要があります。 -
ファイルが存在しない。
.luaファイルが実際にscripts/フォルダに存在するか再確認してください。
3. スクリプトがまったく読み込まれない
症状: コンソールエラーはないが、フックが一切発火しない。
起動時にサーバーコンソールでLua構文エラーがないか確認してください。最も一般的な原因は:
- 関数または
ifブロックを閉じるendの欠落 - 対応しない括弧
- 返されるテーブル内のフック定義間のカンマの欠落
- ファイルが
.luaで終わっていない
Luaエラーがある場合、コンソールはファイル名、行番号、説明を含む[Lua]エラーブロックを出力します。
4. フックが発火しない
症状: スクリプトは読み込まれている([FMM Scripts] Bound scriptメッセージが表示される)が、特定のフックが発火しない。
フック名がフックリファレンスに記載されているとおりに正確に綴られているか確認してください。よくある間違い:
| 間違った名前 | 正しい名前 |
|---|---|
on_click | on_right_clickまたはon_left_click |
on_interact | on_right_click |
on_hit | on_left_click |
on_tick | on_game_tick |
on_remove | on_destroy |
on_arrow_hit | on_projectile_hit |
また、プロップに実際にアーマースタンドエンティティが関連付けられているか確認してください。一部のプロップ設定では、クリック可能なエンティティが生成されない場合があります。
5. タイムアウト / 実行予算の超過
症状: コンソールに次のようなメッセージが表示される:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
スクリプトが1回のフック呼び出しで多すぎる処理を行っていました。一般的な原因:
on_game_tickで多すぎるエンティティを反復処理している- ティックごとに多すぎるパーティクルを生成している
- ティック間で処理を分散せずに負荷の高いループを実行している
解決策: 重い処理をステートベースのクールダウンの後ろに移動するか、on_game_tickの代わりにscheduler:run_repeating()を適切な間隔で使用してください。
6. クリックフックでcontext.eventがnilになる
on_left_clickとon_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()ではサポートされていない特定の追加データが必要です。FLAME、HEART、HAPPY_VILLAGER、NOTE、ENCHANTなどの標準パーティクルを使用してください。
9. サウンドが再生されない
- サウンド名が大文字の有効なBukkit
Sound列挙定数であることを確認してください。例:"BLOCK_NOTE_BLOCK_HARP"であり、"block.note_block.harp"ではありません。 - 位置座標が正しいことを確認してください(すべてゼロやNaNではないこと)。
- ボリュームが0より大きいことを確認してください。
10. ステートが予期せずリセットされる
context.stateはプロップインスタンスごとに存在し、プロップの存続期間中持続します。ステートがリセットされるように見える場合:
- プロップが削除されて再スポーンされた可能性があります(各スポーンで新しいインスタンスが作成されます)。
- スケジューラコールバック内で間違ったコンテキスト変数を使用してステートを読み取っている可能性があります。常にコールバック自身のコンテキストパラメータを使用してください。
遅延設定生成の仕組み
遅延設定システムを理解することで、新しいプロップのセットアップ時の混乱を避けることができます:
-
最初のスポーン: プロップがスポーンし、関連する
.ymlファイルが存在しない場合、FMMは設定を非同期的に作成します。つまり、ファイルはバックグラウンドスレッドで書き込まれ、すぐには利用できません。 -
デフォルト値: 生成される設定には
isEnabled: trueと空のscripts: []リストが含まれます。 -
最初のスポーンではスクリプトなし: 設定はプロップがすでにスポーンした後に作成される(かつスクリプトがリストされていない)ため、最初のスポーンではプロップにスクリプトは割り当てられません。
-
編集して再スポーン: FMMが設定を作成した後、それを編集してスクリプトファイル名を追加します。次にプロップがスポーンする際に、スクリプトが読み込まれます。
-
設定の場所:
.ymlファイルはモデルファイルと同じディレクトリに、同じベース名で作成されます。例:- モデル:
plugins/FreeMinecraftModels/models/fountain.fmmodel - 設定:
plugins/FreeMinecraftModels/models/fountain.yml
- モデル:
- モデルを
models/に配置する - スクリプトを
scripts/に配置する - プロップを一度スポーンする(
.ymlが生成される) .ymlを編集してscripts: [my_script.lua]を追加する- プロップを再スポーンする -- スクリプトが有効になる
エラーメッセージの読み方
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. フックを個別にテストする
複雑なスクリプトを構築する際は、まず各フックを個別にテストしてください。一度に1つのフックを追加し、次に進む前にそれが発火することを確認してください。
5. フック名のタイプミスを確認する
フックが発火しない最も一般的な原因は、フック名のスペルミスです。スクリプトはエラーなしで読み込まれますが、スペルミスのあるフック関数はバリデーション時に拒否されます。
初心者の学習パス
このシステムをゼロから学びたい場合、以下の順序で学習すると効果的です:
api_version = 1とメッセージをログに記録するon_spawnだけを含むファイルを書く。- スクリプトをプロップ設定に追加し、ログメッセージが表示されることを確認する。
on_right_clickを追加し、プロップがクリックされたときにログを記録する。on_left_clickにcontext.event.cancel()を追加して無敵にする。- 右クリックでアニメーションを再生する。
- 右クリックでサウンドを追加する。
- ステートとトグル動作を追加する。
- 近接検知のためにゾーンウォッチを追加する。
- その後で初めて、スケジューラを使った複雑なマルチフックスクリプトに進む。
各ステップは前のステップの上に構築されており、各段階でテストできます。