アドオン製作において誰もが一度は経験しているでしょう。人間がすることには必ずミスが付き物です。もちろんそれはアドオンを作っている時も例外じゃありません。むしろ「何が間違っていたのか」を把握するのが得意でなくて、ミスが見つけられないまま萎えてしまうひとがいるほどです。
そこで、アドオン上級者でも切っても切れない縁にあるのが、トラブルシューティングです。
トラブルシューティングとはなんでしょう?意味を検索すると真っ先にこう出てきます:
トラブルシューティングとは、何らかの原因により発生した異常状態を解決し、正常な状態にするための方法のことである。トラブルシューティングは、あらかじめ想定された異常状態について解決方法がマニュアル化されたものを指すことが多い。
要するにアドオンで何かバグが現れたときに、自分が書いたjsonなどの「何が間違っていたのか」をすぐに把握するためのものです。何かを修理したことがあるひとは感覚が分かりやすいと思います。
「何が間違っていたのか」をすぐに把握できるならば、「ああ、あそこを間違えたのかな」といってチャチャっとそこを直せてしまうわけです。例えば、エンティティを追加したのにスポーンエッグが真っ黒!そしてエンティティ本体が全身透明!──あるあるですね。そこで、ある程度のトラブルシューティングのフローチャートが頭にないと「なんでだよ!?」「はああ......?何が違うんだよ......」と、ストレスを感じたあとに、自分が追加したjsonをイチから全て見直すことになるでしょう。イライラするわ、めんどくさいわの二重苦(?)によって「もう無理だ」と萎えてしまうわけです。アドオン中退者のほとんどに当てはまる理由だと思います。(当てはまらないひとはもやんに追いついてしまった惨めなひとたちかな?)
そこで今回はわたしがほぼ無意識に脳内に組み立てているトラブルシューティングのフローチャートを教えていきたいとおもいます。たぶん誰もトラブルシューティングの記事なんて書いてないと思いますよ......!
※先に言っておきます!この記事ではわたしがちょくちょく”バグ”という言葉を用いてますが、だいたいは”おのれもやん案件”のことではありません!そもそも"バグ"というのは「プログラムやスクリプトを書いた本人が予期しない、おかしい動作をすること」を指すので、アドオン作りでのミスによる予期せぬ動作についても"バグ"と呼ぶことができるということです。今回は「バグ」=「アドオンのスクリプトなどのミスによる予期せぬ動作」という感じで使うことがほとんどです!勝手にもやんに怒らないように、もやんのバグだと思って諦めない/嫌な顔をしないようにしてください!直すのはあなたです!
まずはじめに
アドオンのバグ修正にはいくつか必要なものがあります。
- jsonチェッカー
- スペルチェッカー(あってもなくても)
- 根性
- 諦めない心
です。jsonチェッカーとは、あなたが書いたjsonの文法があってるかどうか校閲をしてくれるものです。アドオン技術者たちはほとんどみんなこれを使っています:
この記事はどうせ長くなるので別の記事に使い方はこっちにまとめました↓
それでは本題に入ろうと思うわけですが、その前に、ごくごく初歩的なミスがないか確認してください。くだらないミスで騒ぐのは屈辱ですよね?
- そもそもアドオンは適用されてますか?
- 試験的なゲームプレイはオンですか?(オフでも追加できるものがほとんどですが、線引きなどをいちいち教えてられないし、そもそもわたしも知らないので基本アドオンで遊ぶときはオンにしましょう)
- そのjsonなどのファイルを入れるのはそのフォルダであってますか?
- ディレクトリ構成を間違っていませんか?
- 本当にその方法で成功したかどうかを確認できていますか?
- 同じコンポーネントを二つ以上書いても全ては動きませんよ?
- その要素は本当に正式実装されてますか?
■エンティティ編
✳変更のみの場合
すでに存在するエンティティに変更を加えただけで起こりうるバグとそれに対するトラブルシューティングです。変更だけでアドオンやめるような深刻なバグはなかなかないですけどね。
①全ての変更が適応されない!
つまりバニラの状態が適応されているので、そもそもjsonの文法が間違っていそうです。jsonチェッカーを通してみてください。
②一部の変更が適応されない!(もしくはその変更の動作がおかしい!)
その変更を加えたコンポーネントなどの要素について、次のことを確認してください。
- 誤字脱字はないか(だいたいスペルチェッカーで見つかる)
- コロン(:)などの記号は半角か
- そのコンポーネントはそのフォーマットバージョンで使えるか(例えばminecraft:area_attackはformat_versionが1.13.0以上じゃないと使えません)→そのバージョンのリファレンスにそのコンポーネントが載っているかどうか
- フィルターの指定を間違っていないか(ドメインがselfかotherかとか、オペレータが==じゃなくて!=になってたとか)
- AI系コンポーネント(コンポーネント名にbehavior.とあるもの)はプレイヤーに追加しても動作しません
- 賢くない初心者が一度は引っ掛かる、”イベントのワナ”にかかってるかも
- environment_sensor、scheduler、damage_sensorに関する変更なら、”コンポーネントの裏仕様”が関わってるかも
○頭を使う?”イベントのワナ”
これは主に、次のようなシチュエイションでよく起こります。
「environment_sensorで指定したアイテムを持ったときに攻撃力が上がるようにしたぞ!」
アドオン作りにある程度なれてきた中級者がよくやる有名なテクニックです。
これでひとつのアイテムだけではつまらないので、だいたいのひとが複数のアイテムに対してそれぞれ異なるイベントを設けます。そこで”フィルターのワナ”に引っ掛かるワケですね。
引っ掛かったひとは、おそらくこんな構成をしていると思います(例):
- アイテムAを持っている→イベントA→コンポーネントグループAを足す
- アイテムBを持っている→イベントB→コンポーネントグループBを足す
- アイテムCを持っている→イベントC→コンポーネントグループCを足す
- アイテムDを持っている→イベントD→コンポーネントグループDを足す
- アイテムA~D全て持っていない→イベントE→上記で足したコンポーネントグループを全て消す
もっと引っ掛かっているひとは四ヶ条目のリセットイベントもないと思います。
これの何がいけないかというと、もしこれでアイテムAからアイテムBに持ちかえたらどうなるでしょう?
コンポーネントグループAが足されたままコンポーネントBがさらに足されませんか?
リセットするイベントは、アイテムAもアイテムBも両方持ってないときに動くので、アイテムAからアイテムBに直接持ちかえると両方持ってない状態を回避することができる、すなわちコンポーネントグループがリセットされません!
もちろん、アイテムAを離したからといってコンポーネントグループAが勝手に消えてくれるなんてことはないわけですから、自分で消す必要があります。さきほどの例をこう修正します:
- アイテムAを持っている→イベントA→コンポーネントグループAを足し、コンポーネントグループB,C,Dを消す
- アイテムBを持っている→イベントB→コンポーネントグループBを足し、コンポーネントグループA,C,Dを消す
- アイテムCを持っている→イベントC→コンポーネントグループCを足し、コンポーネントグループA,B,Dを消す
- アイテムDを持っている→イベントD→コンポーネントグループDを足し、コンポーネントグループA,B,Cを消す
- アイテムA~D全て持っていない→イベントE→上記で足したコンポーネントグループを全て消す
このようにしてeventのaddとremoveを使いこなしましょう。こういったパターンでなくとも、イベントを動かすときはコンポーネントグループをいつ足していつ消すのか考えるクセをつけましょう。
○驚異!初心者殺しの”コンポーネントの裏仕様”
さきほど並べた三つのコンポーネントenvironment_sensor、scheduler、damage_sensorには注意が必要です。
・environment_sensorとscheduler
次のようなシチュエイションを考えます。
「スニークしたときに一度だけ雪玉を発射して、砂漠バイオームへの進入を検知したとき一度だけヒツジが出るようにしたぞ!」
謎なシチュエイションだということは置いておきましょう。これは、特に「スニークしたら何かが出てくる」テクニックの方はやけに初心者に人気ながらもガッツリ中級者向けな、よくあるこれも有名なテクニックです。
このシチュエイションには二つのワナが潜んでいます。まずはじめてこういうものを作ろうとすると、environment_sensorを使ってスニークやバイオームへの進入を検知すると思います。しかし、そうすると一度だけ発射したいのにどうやらスニークしてる間ずっと、砂漠バイオームにいる間ずっと雪玉やヒツジを出し続けるでしょう。
ここでイメージとして、感圧板が乗ったコマンドブロックを思い浮かべてみます。environment_sensorは、感圧板の下に紫色のリピートコマンドブロックです。一方schedulerは感圧板の下にオレンジ色のインパルスコマンドブロックです。
要するに、environment_sensorは検知している間ずっとイベントをリピートして起こし続け、schedulerは検知し始めたはじめの一回だけにイベントを起こします。ということで、イベントを一度だけ起こしたい場合はenvironment_sensorではなくschedulerを使うことをおすすめします。
さて、schedulerに取り替えたところでもうひとつバグが出てきたようです。砂漠バイオームでのみスニークしても雪玉が飛びません。
実はschedulerには、同時に最高ひとつのものしか検知できないという性質があります。つまり、砂漠バイオームへの進入を検知して一度ヒツジを出したけど、砂漠バイオームにいることは検知し続けるのでスニークを検知することができません。ちょっとズレますが、さきほどの感圧板が乗ったインパルスコマンドブロックの感圧板にプレイヤーが乗りながら横からレバーでコマンドブロックを起動しようとしているようなイメージです。
では、どうしたらいいでしょう。実はこれ、難題だったりします。同時に複数検知できるからenvironment_sensorを使おうとはなりません。それだと検知し始めた一度だけという注文を逃してしまっています。
だいぶ前に似たようなことをやろうとしたけど仕様の壁として当時は諦めてしまいました。次から述べる案はこの記事を書きながら考えたもので、試したことはないですが理論上はいけると思います。
1.スニークの方はアニメーションコントローラを使う
最近(この記事を書いてる時期)よく使うテクニックです。「何かを検知してイベントを起こす」ものは何だと問われたら、 environment_sensorとschedulerだけ答えて終わりそうですが、実はアニメーションコントローラも影ながらその仲間だったりします。しかも、アニメーションコントローラならイベントだけでなくコマンドも動かせてしまうので、何気にenvironment_sensorとschedulerに勝っている部分があったりします。
方法は簡単です。トランジションにquery.is_sneakingを入れてスニークを検知してイベントを動かすだけです。スニーク検知のトランジションに戻るときも(1.0)ではなく!query.is_sneakingにしないとenvironment_sensorと同じ動作になることに注意してください。ここで書き方はこれ以上詳しく教えません。
2.バイオーム検知をenvironment_sensorでして、イベント起動をアニメーションコントローラでする
ひとつ前の案と比べると圧倒的に手間なのですが、頭の使い方として一応のせておきます。もしかしたら全部アニメーションコントローラだと検知できないかもしれませんからね。
複数検知できるなら素直にenvironment_sensorを使おうという考え方です。ただし、environment_sensorで検知した後に目的のイベントは動かさずにそれとはまた別のイベントを動かします。それでヴァリアント値を変えましょう。variantが使えなかったらmark_variant、さらにskin_idもあります。はたまたこういう整数型変数じゃなくとも、is_shearedやis_saddledといったブーリアン型変数を使ってもいいですね。言わばビヘイビア界のスコアボードとタグといっても過言ではないものたちです。これらの値ならだいたい全てアニメーションコントローラで検知できるのであとは目的のイベントをアニメーションコントローラで起こすだけです。
3.アニメーションコントローラを使わずにゴリ押す
これは即興で思いついたものでさらに突飛なので、まっったくの未知です。ほんとにできるのかなあ。理論上はできそうです(断言はできない)。まあできなくとも頭の使い方として学んでください。
結局いけないのはschedulerで同時に複数を検知させることですが、バイオーム検知ならそのバイオームに入った後もう検知の必要は無さそうなので、検知対象からはずせばいい訳です。ん?と思って答えの見通しがつかないこともありそうなのでとりあえず方法を述べます。
- スニーク検知もバイオーム検知もまずはschedulerでやる
- バイオームへの進入を検知したら動くイベントをイベントAとする
- イベントAで動くコンポーネントグループに検知したバイオーム以外の、スニーク検知とかを含んだschedulerを置く
- そのバイオームから出たかどうかをそのコンポーネントグループ内のenvironment_sensorで検知する
- そのバイオームから出たらイベントAで追加したコンポーネントグループを消す
また新たなバグが見つかりそうな古典的かつだいぶゴリ押してる方法ですが、たしかに注文は叶えられていそうです。
わたしが書いておいて言うのもアレですが、この方法は少し賢い方法だと思います。もしかしたらこの解説でわからないひともいるかもしれませんが詳しい解説は省略します。
・damage_sensor
長々と話してしまいましたが、裏仕様があるコンポーネントの三つ目、damage_sensorについてです。あんまり多用しないと思いますが、わりといろんなダメージ要因を検知してそのダメージの効果の有無を変えられたりします。さらにフォーマットバージョンが1.13.0以上ならそのダメージによるダメージの軽減率も決められます。
そんな、影ながら便利なコンポーネントですが、影ながら潜んでいる性質があります。その性質とは、jsonに書いた上から順にフィルターを比較していき、条件を満たすならばそれ以降のフィルターは比較されない、というものです。
例えば、金床によるダメージを軽減し、それとは別に死んでしまったときに何かイベントが起こるようにするとします。これをjsonに書いたときに金床の部分を先に書いてしまうと、金床で死んでもイベントは動きません。それを踏まえてフィルターの順序をうまく並び替えましょう。もしくはこれを逆手にとって金床で死んだときだけイベントが動かないようにしたければわざとそうするのもアリです。
書く順番によって動作が異なる、というのはなかなか珍しいです。アドオンのなかでも他にシェーダぐらいしか知りません。
✳カスタムエンティティ(自分で追加したエンティティ)の場合
①そもそも追加できない!
- だいたいその場合はjsonの文法をミスしてると思います。jsonチェッカーにかけてみましょう。
- アイデンティファイア(identifier)の決め方がいけないのかもしれません。接頭辞にminecraft:は使えませんし、名前に数字を使うのは避けたほうがいいです。
- スポーンエッグの有無やコマンドの/summonで追加できてるか否かを決めていませんか?デスクリプション(desription)の中にあるis_spawnableがtrueじゃないとスポーンエッグは存在しませんし、is_summonableがtrueじゃないとコマンドで/summonできません。はじめは全部trueにして追加の確認がとれてからfalseにしましょう。
②追加できたけど透明!しかもスポーンエッグが真っ黒!
一番のあるあるですね。この場合ビヘイビアはできていますが、リソースの.entity.jsonに問題があります(エッグが黒いのが証拠)
- リソースの.entity.jsonファイルをjsonチェッカーに通してみてください。
- デスクリプションの中身はmin_engine_versionとenable_attachables以外省略できません。何か省略していませんか?
- アイデンティファイアに誤字脱字はありませんか?
- min_engine_versionをつけたりはずしたりしてみてください
③追加できて透明だけどスポーンエッグの色・テクスチャは適用されてる!
.entity.jsonが合っているのにエンティティが透明だという場合は、だいたいジオメトリ、レンダーコントローラのいずれかが間違っています。
- ジオメトリの名前に誤字脱字はありませんか?
- レンダーコントローラの名前に誤字脱字はありませんか?
- 指定するマテリアルはあってますか?
- .entity.jsonでジオメトリやレンダーコントローラの指定を間違っていませんか?
- ジオメトリの を間違っていませんか?間違ってテクスチャがない部分を指定してるかもしれません。
- レンダーコントローラでのテクスチャ、ジオメトリの指定を間違っていませんか?
あとは変更のみの場合と重なると思います。
■ビヘイビアのアニメーションコントローラ(アニメーション)編
バグのケースが無数にあるのでミスを探すポイントを列挙していきます。
- アニメーションコントローラまたはアニメーション、それらを動かすエンティティのjsonをチェッカーに通す・誤字脱字を確認する
- アニメーションコントローラやアニメーションを動かすエンティティのjsonにて、scriptsとanimationsの書き方が合っているかどうか・指定ミスがないか
- 層の構成はanimation_controllers>controller.animation.○○、controller.animation.□□>states>default、△△ >transitions, on_entry, on_exitであるか
- トランジションで(1.0)ではなく(1,0)と書いていないか 点はカンマじゃなくてピリオドです。
- そもそもそのコマンドやイベントは動いているか コマンドなら別のもっと簡単なコマンドを、イベントはエンティティで動かしてみるなどしてみましょう。
- 変数宣言をしたときに、最後にセミコロン(;)をつけ忘れていないか
■ブロック編
①そもそも追加されない!
- jsonをチェッカーに通す・誤字脱字を確認する
- アイデンティファイアの決め方が悪くないか
- register_to_creative_menuをtrueにしていないとクリエイティブインベントリには出ません
- block_light_emissionの値は0.0~1.0の間に収まっているか
- /setblockでブロックを設置するときはアイデンティファイアの接頭辞は必要ないです
②全身灰色のテクスチャになってる!or ピンクと黒のチェック柄(ミスイングテクスチャ)になってる!or update!のテクスチャになってる!
だいたいリソースblocks.jsonかterrain_texture.jsonのミスです。灰色の場合はblocks.json、ミスイングテクスチャの場合はterrain_texture.jsonでミスをしていることが多いです。以前はblocks.jsonでミスをすると、ワールド生成時にクラッシュまたはその追加したブロックが視界に入るとクラッシュするということがありました。
- blocks.jsonかterrain_texture.jsonをチェッカーに通す・誤字脱字を確認する
- blocks.json内かterrain_texture.json内の指定ミス
■アイテム編
①そもそも追加されない!
- jsonをチェッカーに通す・誤字脱字を確認する
- 少なくともこの記事を書いている時期にはクリエイティブインベントリに陳列されないバグがあります
②テクスチャが透明!
- リソースのitemsフォルダのjsonかitem_texture.jsonにミスがあります
■レシピ編
①そもそも追加されない!
- jsonをチェッカーに通す・誤字脱字を確認する
- キーの定義がしっかりなされているか
- データ値を間違っていないか
■バイオーム編
- バイオームタグにrareがついていませんか?rareをはずしてplainsをつけると確率が上がります。
- ファイル名とアイデンティファイアは同じですか?
- 既存のバイオームと見間違えていませんか?
- バイオームタグを追加することによってフィーチャーがつきます。
■フィーチャー・フィーチャールール編
- jsonをチェッカーに通す・誤字脱字を確認する
- そのフィーチャーを適用するバイオームタグは適用させたいバイオームについていますか?
- jsonの紐付けは正しくできていますか?(aggregateなど)
- extentの値を広くしてみたり、iterationsの値を大きくして生成の確率や個数を多くしてみる
- 鉱石型のcountは3以上でないと生成されません
- ファイルの名前とアイデンティファイアの名前を揃えてみる
- データ値のあるブロックはダメかもしれません。
■リソースのアニメーションコントローラ(アニメーション)編
右手だけが動かない、とかの場合はだいたいここです。アニメーションを自作しない限りなかなか間違えません。
- jsonをチェッカーに通す・誤字脱字を確認する
- .entity.jsonのscriptsで定義していない変数を使っていないか
- .entity.jsonで指定のミスがないか
- ジオメトリ内とアニメーション内でボーンの名前が異なっていないか
- 時間変数に大きい数をかけて動きを大きくする
- 数が大きくて視界に入っていなかったことがないか、常にゼロ除算している状態でないか
- ボーンが遠くにあるとき、エンティティの本体を視界に入れないと消えてしまいます
■パーティクル編
- jsonをチェッカーに通す・誤字脱字を確認する
- emitter_rate_manualを使うと動作しないというのがあったんですが、今はどうなんでしょう
- テクスチャのuv指定を間違っていないか
- particle_appearance_billboardのsizeの値が小さすぎないか
- positionの値が大きすぎて視界に入っていなかったことがないか、常にゼロ除算をしている状態でないか
■シェーダ編
シェーダでミスをすると、だいたい全てが透明になるか、変更が通用しないのどちらかです。そして、シェーダはC言語で書かれているので、もちろんjsonチェッカーに通しても無駄です。
- セミコロンのつけ忘れがあるかどうか・その他誤字脱字
- 小数を入れるところに整数を入れてないか(たとえ1でも1.0と書く必要があります)
- 定義・宣言されてない変数を使っていないか includeし忘れていないか
- 処理を書く順番が合っているかどうか(使う変数が定義・宣言される前、値を代入される前に書いてももちろんダメですからね)
- 動かしたい処理にコメントアウトがかかっていないか
- スマホならglsl、win10ならhlslをちゃんと使用してますか?
■マニフェスト編
ここにミスがある場合、そもそもアドオンを導入ことがあります。
- UUIDがかぶっている可能性があります
- マイクラ本体のバージョンにあっていますか?
- ビヘイビアのマニフェストとリソースのマニフェストを逆にしていませんか?
■その他
○/functionが動かない!
- マニフェストにmin_engine_versionを書きましたか?
- そもそもコマンドはあっていますか?
○.langファイルで変更を加えたら「#」がついた
- Tabスペースでスペースを開けないと表示されてしまいます
○カスタムエンティティが自然に湧かない!
- difficulty_filterを満たす難易度でプレイしていますか?
- weightが小さすぎるかもしれません。通常は200です。
- brightness_filterを満たす光源レベルですか?
- ネザーに湧かせたい場合はspawns_undergroundをつける必要があります
○attachableの変更が反映されない!
- 現在変更できない仕様となっています
○fontの追加ができない!
- 新しくファイルを追加することはできません 追加する場合はglyph_E0.pngやglyph_E1.pngなどの空白に描き足しましょう
○エンティティのテクスチャが透けない!
- .tgaファイルに変換して、マテリアルをslime_outerなどにする必要があります
ひとまずこれで終わりです。これで全て切り抜けるということはなかなかないでしょう。もしここに書いてあることを全て試してもダメなら技術者に聞きましょう。そして、後で思い出したら追加していくと思います。
■最後に
トラブルシューティングをしていく上でいくつか考慮しておくべきことがいくつかあります。
①jsonの文法があっていても、マイクラが許さない場合がある
当たり前といえば当たり前です。カッコの数を間違えると確実に文法ミスになりますが、カッコの位置が違うだけなら文法ミスにならないことがあります。英語でも、文法があってるのにそういう言い方はしないな、ということがあるのと似たような感じです。
②存在する英単語でミスをするとスペルチェッカーも気づかない
例えば「entry」を「entity」と間違えるといった感じです。それはそう、なんですがこれも念頭に入れておかないと迷宮入りしてしまうことがあります。
③「どうせ大丈夫」こそ迷宮への入り口
これも当たり前ですが、根気よく隅々まで探さないと本当に迷宮入りします。だいぶはじめの方に書いた「同じコンポーネントを二つ以上書いても全ては動きません」なんて誰が間違うかよなんて思うかもですが、現にわたしはやらかしています。思ってもみなかったところにこそミスはあります。しかもミスは上級者になっていくほど見つけるのが難しくなったりします。
④一度にたくさんの変更・追加をしない
ミスが深刻な場合、ワールド生成時にクラッシュすることがあります。そうなったときにエンティティ、ブロック、アイテム、バイオーム、フィーチャー、などなどたくさんのもの変更・追加をしたとしましょう。どれが原因か全くわかりません。そうです、全部見なくてはなりません。そのためにもコツコツとエンティティだけ、ブロックだけ、アイテムだけ、といったようにある程度原因がしぼれるように追加することを心がけましょう。
そして、いま自分が何を変更・追加したかを覚えておきましょう。そうすれば「いまここを変更してクラッシュしたからここのどこかが悪いんだな」と簡単にしぼりこむことができます。
はじめのうちはこれを見ながらいろいろ照らし合わせて原因を探って、最終的には大体ぜんぶ頭にいれてバグの”症状”を見ただけで「ああ、あそこかな」となればもう怖いものなしでしょう。そして意味わからないバグに苛まされて萎えることもだいぶなくなると思います。
最後に、恒例ですが何か間違い・不足があったら教えてください!
少し補足があったほうがいいと思った箇所についてはこっちに補足がされています↓
0コメント