【ウディタSRPG】バグ修正①

銀日記さんのSRPGの仕組みはおおよそ理解できた(という気になってる)ので、これを元に改造していきます。


が、その前に、配布されているデータにバグっぽいものがあったので、自分なりに調べて修正してみました!


見ての通り、基本的には敵ユニットの処理にバグらしきものが見られました。


おこがましいのは重々承知の上で、修正していきますw
ここ最近のウディタ勉強の成果を見せたるで!!!(誰


あそうそう、もしかしたら僕みたいにSRPGを制作したくてもどっから手を付ければいいかわかんない!って方がいるかもしれないので、備忘録というかちょっと講座っぽく?しばらくの間は書いていこうと思います。


コモンEv47[■ターゲッティング(最短)]が正常に機能しない

このコモンEvでは名前の通り、処理中のユニット(自分自身)から最も近いユニットを探索する処理をしているんですが、実際の処理を読んでみると...

7,8行目CSelf0を参照してます。


このCSelf0は何者かというと、引数として渡される処理中のユニット(自分自身)のx座標なんです。
実際、コモンEv入力内容を見てみるとxとして設定されています。

このままだとx座標のx座標x座標のy座標とかいう意味不明なコードになってしまう上、CSelf12[距離]常に0になってしまいますね。


つまり、このコモンEvの結果(CSelf15[タゲID])の値も常に0という事になってしまうので、敵ユニットは必ずマップEvID0番をターゲットにするという仕様になってしまうわけです。


というわけで、ここは正しく相手ユニットの座標をセットできるようにしましょう。

以下の通り、CSelf13[処理ID]を参照すれば良いですね。

「相手のx座標」と「相手のy座標」


敵ユニットが座標(0,0)を目指して移動する

極端な例ですが、例えばユニットの配置がこんな具合になっている場合。

敵ユニットは座標(0,0)を目指しながら所構わず当たり散らします...

これが暴走ってやつですね(違う


こうなってしまう理由はコモンEv46[■評価値計算]にあったのですが、いきなりそれを説明してもワケマカメだと思うので、先に敵ユニットの行動をどう決定しているかの仕組みについて解説しておきます。


まずはこれ↓を見てください。

ちょっと見づらくてすみませんww


画像左側のコモンEv45[■敵AI処理]内で敵ユニットが移動できる座標を判定して、その座標一つ一つに対して、画像右側のコモンEv46[■評価値計算]で点数を付けてもらってます。

間に書いてある文章のやり取りはあくまでイメージで、実際にはコモンEv46[■評価値計算]からは評価値を始め、攻撃先の座標なんかも返ってくるようになってます。


このコモンEv46[■評価値計算]では、コモンEv45[■敵AI処理]から渡された(聞かれた)座標からどの座標に向かって攻撃するのが一番良いかという計算をしています。
場合によっては攻撃しないほうが良い(周りに攻撃できる相手がいない)という計算結果も出ます。


で、最終的に敵ユニットはコモンEv45[■敵AI処理]の指示で一番評価値が高かった座標に移動するわけですね。


これを踏まえてコモンEv46[■評価値計算]を見てください。

5行目~18行目で行っている処理は、相手に接近するが攻撃しないパターンの評価なのですが、この時、評価中の座標と最も近い相手のユニット=ターゲットとの距離をそのまま評価値の計算に利用しています。


つまり、相手との距離が長いほど評価値が低いという計算にしなければならないので、12行目で謎に15という数字から引き算をしているわけですね。



ここで、なんで単純に
(評価値) = (距離) × (-1)
にしないの?
と思われるかもしれませんが、距離をそのまま正負逆転させてしまうと評価値が0より小さくなるのでマズイんですよ。




なぜ評価値が0より小さいとマズイのか?


まず、評価値の記録は可変DB[AI計算用紙②]で管理してるのですが、この項目「評価値」って、初期値が0なんですよね。


そして評価値の計算はざっくり説明すると以下のように行われています。

  評価値の計算
 1.移動先座標で攻撃を実行した時、相手のユニットに当たる場合は1機につき +30
 2.移動先座標で攻撃を実行した時、味方のユニットに当たる場合は1機につき -10


例えば。
敵ユニットの8マス先にターゲットとなるユニットが存在する場合、
データ番号0番には相手に接近するが攻撃しないパターンの評価値として
(評価値)= 15 - 8 = 7
が記録されます。


以降、可変DB[AI計算用紙②]には以下のように評価値が記録されていきます。

もちろん敵ユニットの持つスキルの射程圏内に相手のユニットが存在したり、仲間のユニットが存在すればこの評価値は上で説明した通り30とか-10とかになります。
ですが射程圏内にユニットが一切存在しないと評価値は初期値の0のまま記録されていくのです。



このコモンEv46[■評価値計算]では最後に、可変DB[AI計算用紙②]の項目「評価値」が一番大きいデータを判別し、各項目(攻撃先座標や使用スキル)を返り値(結果)としてCSelf5にセットする処理になっています。


つまり、どこに攻撃をしても相手のユニットに当たらない(=評価値が0より大きいパターンがない)場合、データ番号0番相手に接近するが攻撃しないパターンの評価値が一番高いので、これが返り値(結果)としてCSelf5にセットされるわけですね。



逆に言えば、データ番号0番相手に接近するが攻撃しないパターンの評価値が0より小さくなってしまうと、他の評価値0=誰にも当たらないのに攻撃する行動が有効と判断されてしまうわけです。


なので、相手に接近するが攻撃しないパターンの評価値が0より小さくならないように、わざわざ15という基準値を決めて、
(評価値)= 15 - (自分と相手の距離)
という計算をしているわけです。


ですが、これはあくまで15マス以内にターゲットとなるユニットが存在する場合のシナリオ。


例えば敵ユニットの20マス先にターゲットとなるユニットが存在する場合、可変DB[AI計算用紙②]には以下のように評価値が記録されていきます。


もうおわかりですね。


データ番号0番の相手に接近するが攻撃しないパターンの評価値が0より小さくなってしまうと、評価値0の無意味な行動が有効と判断されてしまうのです。


敵ユニットは、評価値0=本来選択されないはずの無意味な行動をしていた
ちなみに座標(0,0)を目指してしまう理由は、左上のマスから評価値を計算しているからです。






ここまでわかれば何を修正すれば良いのか明白です。


そう、基準値が全ての元凶っだったわけです。
実際、敵ユニットと味方ユニットが15マス近く離れているとこのバグが発生します。
相手に接近するが攻撃しないパターンの評価値が0より小さくなってしまうからですね。


実はこの事は銀日記さんの講座第12回でも軽く?触れられています。
なのでこれはバグ修正というより改良?と言った方がいいのかも。

このマップサイズは30×20なので、基準値を15ではなく50にしておけばまず問題ないですね~。











が、これが実は落とし穴なんですよね...

この方法だと逆に、基準値が高すぎて何もしないほうが評価値が高いという結果になってしまうので、もう一工夫必要です。


長くなってきましたが、頑張りましょう。




ずばり、上記問題の解決方法は他にもあります。
それは何もしない評価値ターゲットまでの距離の評価値を別々にする、というもの。


先に距離の長さを単体で評価値として計算してしまうから面倒なんですよ。
面倒な事は後回しにしてやれば良いのです!!!



というわけでまずは距離に関するコードをごっそり削除します。
代わりに評価値には基準値の15をセットしておきます。
これで評価値0の行動が優先されるなんて事は起きなくなりましたね。



では次に、有効と判定された評価値が相手に接近するが攻撃しないパターン(スキルID=-1の場合)なら、距離を評価値として計算・評価値に加えましょう。
上で削除した処理と内容は同じです。


これで敵ユニットがどんなに離れていても正常に動きます。


お疲れさまでした。長くなってしまったので後半は次回で!

コラム

余談ですがウディタには豊富なデバッグ機能が搭載されているとはいえ、ブレークポイントを貼れないので、仮にエラーが生じた場合にその個所を特定するのが難しかったりします。
そんな時は原因と思われる箇所(わからない場合はコードを呼んで処理を追う)に、その時点で各値にどんな値がセットされているのかを見ていくと良さそうです。

もちろんデバッグ文でも良いのですが、個人的には処理を止めて一つずつ丁寧に見ていけるので、文章の表示の方が性に合ってそうです。
いちいちこんな丁寧に表示させなくても良いですけどネ