Ameba Ownd

アプリで簡単、無料ホームページ作成

MinecraftBEアドオン-ヒント倉庫

何が違うの!?そんなときのトラブルシューティング

2020.03.27 05:28

 アドオン製作において誰もが一度は経験しているでしょう。人間がすることには必ずミスが付き物です。もちろんそれはアドオンを作っている時も例外じゃありません。むしろ「何が間違っていたのか」を把握するのが得意でなくて、ミスが見つけられないまま萎えてしまうひとがいるほどです。

 そこで、アドオン上級者でも切っても切れない縁にあるのが、トラブルシューティングです。

 トラブルシューティングとはなんでしょう?意味を検索すると真っ先にこう出てきます:

トラブルシューティングとは、何らかの原因により発生した異常状態を解決し、正常な状態にするための方法のことである。トラブルシューティングは、あらかじめ想定された異常状態について解決方法がマニュアル化されたものを指すことが多い。

 要するにアドオンで何かバグが現れたときに、自分が書いたjsonなどの「何が間違っていたのか」をすぐに把握するためのものです。何かを修理したことがあるひとは感覚が分かりやすいと思います。

 「何が間違っていたのか」をすぐに把握できるならば、「ああ、あそこを間違えたのかな」といってチャチャっとそこを直せてしまうわけです。例えば、エンティティを追加したのにスポーンエッグが真っ黒!そしてエンティティ本体が全身透明!──あるあるですね。そこで、ある程度のトラブルシューティングのフローチャートが頭にないと「なんでだよ!?」「はああ......?何が違うんだよ......」と、ストレスを感じたあとに、自分が追加したjsonをイチから全て見直すことになるでしょう。イライラするわ、めんどくさいわの二重苦(?)によって「もう無理だ」と萎えてしまうわけです。アドオン中退者のほとんどに当てはまる理由だと思います。(当てはまらないひとはもやんに追いついてしまった惨めなひとたちかな?)


 そこで今回はわたしがほぼ無意識に脳内に組み立てているトラブルシューティングのフローチャートを教えていきたいとおもいます。たぶん誰もトラブルシューティングの記事なんて書いてないと思いますよ......!


※先に言っておきます!この記事ではわたしがちょくちょく”バグ”という言葉を用いてますが、だいたいは”おのれもやん案件”のことではありません!そもそも"バグ"というのは「プログラムやスクリプトを書いた本人が予期しない、おかしい動作をすること」を指すので、アドオン作りでのミスによる予期せぬ動作についても"バグ"と呼ぶことができるということです。今回は「バグ」=「アドオンのスクリプトなどのミスによる予期せぬ動作」という感じで使うことがほとんどです!勝手にもやんに怒らないように、もやんのバグだと思って諦めない/嫌な顔をしないようにしてください!直すのはあなたです!


まずはじめに

 アドオンのバグ修正にはいくつか必要なものがあります。

です。jsonチェッカーとは、あなたが書いたjsonの文法があってるかどうか校閲をしてくれるものです。アドオン技術者たちはほとんどみんなこれを使っています:

 この記事はどうせ長くなるので別の記事に使い方はこっちにまとめました↓


 それでは本題に入ろうと思うわけですが、その前に、ごくごく初歩的なミスがないか確認してください。くだらないミスで騒ぐのは屈辱ですよね?

■エンティティ編

✳変更のみの場合

 すでに存在するエンティティに変更を加えただけで起こりうるバグとそれに対するトラブルシューティングです。変更だけでアドオンやめるような深刻なバグはなかなかないですけどね。

①全ての変更が適応されない!

 つまりバニラの状態が適応されているので、そもそもjsonの文法が間違っていそうです。jsonチェッカーを通してみてください。

②一部の変更が適応されない!(もしくはその変更の動作がおかしい!)

 その変更を加えたコンポーネントなどの要素について、次のことを確認してください。

○頭を使う?”イベントのワナ”

 これは主に、次のようなシチュエイションでよく起こります。

 「environment_sensorで指定したアイテムを持ったときに攻撃力が上がるようにしたぞ!」

 アドオン作りにある程度なれてきた中級者がよくやる有名なテクニックです。

 これでひとつのアイテムだけではつまらないので、だいたいのひとが複数のアイテムに対してそれぞれ異なるイベントを設けます。そこで”フィルターのワナ”に引っ掛かるワケですね。

 引っ掛かったひとは、おそらくこんな構成をしていると思います(例):

 もっと引っ掛かっているひとは四ヶ条目のリセットイベントもないと思います。

 これの何がいけないかというと、もしこれでアイテムAからアイテムBに持ちかえたらどうなるでしょう?

 コンポーネントグループAが足されたままコンポーネントBがさらに足されませんか?

 リセットするイベントは、アイテムAもアイテムBも両方持ってないときに動くので、アイテムAからアイテムBに直接持ちかえると両方持ってない状態を回避することができる、すなわちコンポーネントグループがリセットされません!

 もちろん、アイテムAを離したからといってコンポーネントグループAが勝手に消えてくれるなんてことはないわけですから、自分で消す必要があります。さきほどの例をこう修正します:

 このようにして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で同時に複数を検知させることですが、バイオーム検知ならそのバイオームに入った後もう検知の必要は無さそうなので、検知対象からはずせばいい訳です。ん?と思って答えの見通しがつかないこともありそうなのでとりあえず方法を述べます。

  1. ​スニーク検知もバイオーム検知もまずはschedulerでやる
  2. バイオームへの進入を検知したら動くイベントをイベントAとする
  3. イベントAで動くコンポーネントグループに検知したバイオーム以外の、スニーク検知とかを含んだschedulerを置く
  4. そのバイオームから出たかどうかをそのコンポーネントグループ内のenvironment_sensorで検知する
  5. そのバイオームから出たらイベントAで追加したコンポーネントグループを消す

 また新たなバグが見つかりそうな古典的かつだいぶゴリ押してる方法ですが、たしかに注文は叶えられていそうです。

 わたしが書いておいて言うのもアレですが、この方法は少し賢い方法だと思います。もしかしたらこの解説でわからないひともいるかもしれませんが詳しい解説は省略します。

・damage_sensor

 長々と話してしまいましたが、裏仕様があるコンポーネントの三つ目、damage_sensorについてです。あんまり多用しないと思いますが、わりといろんなダメージ要因を検知してそのダメージの効果の有無を変えられたりします。さらにフォーマットバージョンが1.13.0以上ならそのダメージによるダメージの軽減率も決められます。

 そんな、影ながら便利なコンポーネントですが、影ながら潜んでいる性質があります。その性質とは、jsonに書いた上から順にフィルターを比較していき、条件を満たすならばそれ以降のフィルターは比較されない、というものです。

 例えば、金床によるダメージを軽減し、それとは別に死んでしまったときに何かイベントが起こるようにするとします。これをjsonに書いたときに金床の部分を先に書いてしまうと、金床で死んでもイベントは動きません。それを踏まえてフィルターの順序をうまく並び替えましょう。もしくはこれを逆手にとって金床で死んだときだけイベントが動かないようにしたければわざとそうするのもアリです。

 書く順番によって動作が異なる、というのはなかなか珍しいです。アドオンのなかでも他にシェーダぐらいしか知りません。

✳カスタムエンティティ(自分で追加したエンティティ)の場合

①そもそも追加できない!

②追加できたけど透明!しかもスポーンエッグが真っ黒!

 一番のあるあるですね。この場合ビヘイビアはできていますが、リソースの.entity.jsonに問題があります(エッグが黒いのが証拠)

③追加できて透明だけどスポーンエッグの色・テクスチャは適用されてる!

 .entity.jsonが合っているのにエンティティが透明だという場合は、だいたいジオメトリ、レンダーコントローラのいずれかが間違っています。

 あとは変更のみの場合と重なると思います。

■ビヘイビアのアニメーションコントローラ(アニメーション)編

 バグのケースが無数にあるのでミスを探すポイントを列挙していきます。

■ブロック編

①そもそも追加されない!

②全身灰色のテクスチャになってる!or ピンクと黒のチェック柄(ミスイングテクスチャ)になってる!or update!のテクスチャになってる!

 だいたいリソースblocks.jsonかterrain_texture.jsonのミスです。灰色の場合はblocks.json、ミスイングテクスチャの場合はterrain_texture.jsonでミスをしていることが多いです。以前はblocks.jsonでミスをすると、ワールド生成時にクラッシュまたはその追加したブロックが視界に入るとクラッシュするということがありました。

■アイテム編

①そもそも追加されない!

②テクスチャが透明!

■レシピ編

①そもそも追加されない!

■バイオーム編

■フィーチャー・フィーチャールール編

■リソースのアニメーションコントローラ(アニメーション)編

 右手だけが動かない、とかの場合はだいたいここです。アニメーションを自作しない限りなかなか間違えません。

■パーティクル編

■シェーダ編

 シェーダでミスをすると、だいたい全てが透明になるか、変更が通用しないのどちらかです。そして、シェーダはC言語で書かれているので、もちろんjsonチェッカーに通しても無駄です。

■マニフェスト編

 ここにミスがある場合、そもそもアドオンを導入ことがあります。

■その他

​○/functionが動かない!

○.langファイルで変更を加えたら「#」がついた

○カスタムエンティティが自然に湧かない!

○attachableの変更が反映されない!

○fontの追加ができない!

○エンティティのテクスチャが透けない!


 ひとまずこれで終わりです。これで全て切り抜けるということはなかなかないでしょう。もしここに書いてあることを全て試してもダメなら技術者に聞きましょう。そして、後で思い出したら追加していくと思います。


■最後に

 トラブルシューティングをしていく上でいくつか考慮しておくべきことがいくつかあります。

①jsonの文法があっていても、マイクラが許さない場合がある

 当たり前といえば当たり前です。カッコの数を間違えると確実に文法ミスになりますが、カッコの位置が違うだけなら文法ミスにならないことがあります。英語でも、文法があってるのにそういう言い方はしないな、ということがあるのと似たような感じです。

②存在する英単語でミスをするとスペルチェッカーも気づかない

 例えば「entry」を「entity」と間違えるといった感じです。それはそう、なんですがこれも念頭に入れておかないと迷宮入りしてしまうことがあります。

③「どうせ大丈夫」こそ迷宮への入り口

 これも当たり前ですが、根気よく隅々まで探さないと本当に迷宮入りします。だいぶはじめの方に書いた「同じコンポーネントを二つ以上書いても全ては動きません」なんて誰が間違うかよなんて思うかもですが、現にわたしはやらかしています。思ってもみなかったところにこそミスはあります。しかもミスは上級者になっていくほど見つけるのが難しくなったりします。

④一度にたくさんの変更・追加をしない

 ミスが深刻な場合、ワールド生成時にクラッシュすることがあります。そうなったときにエンティティ、ブロック、アイテム、バイオーム、フィーチャー、などなどたくさんのもの変更・追加をしたとしましょう。どれが原因か全くわかりません。そうです、全部見なくてはなりません。そのためにもコツコツとエンティティだけ、ブロックだけ、アイテムだけ、といったようにある程度原因がしぼれるように追加することを心がけましょう。

 そして、いま自分が何を変更・追加したかを覚えておきましょう。そうすれば「いまここを変更してクラッシュしたからここのどこかが悪いんだな」と簡単にしぼりこむことができます。



 はじめのうちはこれを見ながらいろいろ照らし合わせて原因を探って、最終的には大体ぜんぶ頭にいれてバグの”症状”を見ただけで「ああ、あそこかな」となればもう怖いものなしでしょう。そして意味わからないバグに苛まされて萎えることもだいぶなくなると思います。


 最後に、恒例ですが何か間違い・不足があったら教えてください!


 少し補足があったほうがいいと思った箇所についてはこっちに補足がされています↓