スクリプトエラー撲滅キャンプ(2) 続NoMethodError
スクリプト導入でエラーが出る人や、手探りで書いてみてエラーが出る人の参考になれば。
あくまで私の知識と経験則に基づいているのと
ツクール始めたての人には流石に難しいかもしれない
という2点は先にお断りしておきますね。
第二回も引き続きNoMethodErrorの対処法を見ていきましょう。
原因その4「ローカル変数が定義されてない」
ローカル変数というのはそのメソッドの中だけの一時的な変数です。
ヘルプにも載っていますがメソッド呼び出しと同じ書き方をするため
エラーもNoMethodErrorという形で報告されます。
ローカル変数を使うためには「メソッド内で定義(=代入)する」決まりがあります。
def abcこの場合だと1行目でtestがローカル変数として定義されているので
test = 0
test += 1
end
「ああ、testは0だからそれに1を足すのね」と理解してくれます。
ところがいきなり2行目だけ書くと
「testって何?そんなメソッドないよ!あーもう駄目だエラー出してやる!」
とヒスってNoMethodErrorになります。時々NameErrorにもなります。
原因その5「文字列""の付け忘れ」
スクリプトの決まりで、文字列は""で囲うというものがあります。
def abcこの例ではちゃんと@nameに「アレックス」という文字列が入ります。
@name = "アレックス"
end
しかし@name = アレックスと書くと「def アレックス」の参照と見なされるため「アイヤー(ry」となります。
原因その6「インスタンス変数にアクセスできない」
インスタンス変数@は便利なので多用されていますが
呼び出しにちょいと制約があるためアクセサという仕組みを使って呼び出されます。
例えば@abcにアクセスしたいがエラーになった場合
まずattr_writer :abcやattr_reader :abcを探して、これをattr_accessor :abcに差し替えます。
或いは↑がない場合でもどのクラスのインスタンス変数か理解しているなら
直接attr_accessor :abcを追加してアクセス可能にすることも出来ます。
それから、実際にGame_Actorにある例ですが
def idこんな形でアクセサが組まれていることがあります。
@actor_id
end
この場合だと@actor_idを参照する書き方が
×@actor.actor_id
○@actor.id
となります。この辺りはとにかく検索して試していくのが近道かと思っています。
原因その7「nilの子はnil」
最後に、一見すると問題がなさそうな記述で起こるエラーです。
イベントのすゝめ(10)でちょろっと触れていますが
nilが入っている変数より以下のメソッドを参照してしまうとエラーになります。
特に$game_actorsの様な多段の入れ子構造になっているもので起きやすく
「IDを指定して特定のアクターを呼び出す」「ループで全てのアクターを呼び出す」処理には
ifやunlessを上手く使ってnilを弾くようにする必要があります。
実際の楽~な探し方は?
というわけでNoMethodErrorは実際いくつものパターンがあります。
ここまで長々と読まれてうんざりしてきた方もいると思いますが
これを全て頭に叩き込め、1つ1つ確認していけ!などと言うつもりはありません。
効率的な調べ方で存分に手を抜きましょう。
まず最初にするのがスクリプトの全検索です。
候補がない、明らかに関係のないクラスのものしかない場合は
ヘルプの方にもキーワード検索をかけます。
・エラー箇所以外にはヒットしない
その1のスペルミスか、その5の""の付け忘れ
その4のローカル変数の宣言し忘れが考えられます。
・幾つかヒットするがdef ○○というのがない
その2のメソッドがない可能性が高いです。
・@○○ばかりがヒット
その6のアクセサをチェックしてみましょう。
・沢山ヒットするし、問題がなさそう
その3のメソッドとの関係性や、その7のnil関係を探ります。
pを使えばコンソールに変数の中身を表示できるので
エラー箇所で使われている変数のクラスやnil含みを調べていきます。
最悪自力で解決できなくとも、ここまで絞り込めば質問もスムーズに行くでしょう。