【ウディタ】複数の並列実行から同じコモンEvを呼び出す場合の注意点

今回作成したNPC自由移動システムでは、移動可能な出入り口の数だけ並列実行を使用したんですが、そこでちょっと苦戦した事があります。

コモンセルフ変数が上書きされる

コモンEvを呼び出した時、その処理はあくまで静的に扱われ、オブジェクト指向でいうところのインスタンスみたいな事はできない。
これはコモンセルフ変数セーブデータに保存されることを考えれば当然。


つまり、複数の並列実行から同じコモンEvを呼び出す場合、コモンセルフ変数は共通のものを使用することになりますね。

マップイベント(並列)1→攻撃コモン
マップイベント(並列)2→攻撃コモン
と同時に処理させた場合に攻撃コモンの変数を1と2で共有してる感じでした。



調べたところ、そもそも並列実行って厳密には同時実行というわけでは無いようで。

複数の並列実行を同時に実行した場合もイベントID順に処理され、1つのイベント処理が終わったら、次のイベント処理が実行されます。


但し複数の並列実行を実行している時に、並列実行の中でウェイトを実行すると、ウェイトで処理が停止している間は、別の並列実行が実行されます。


この仕様によって何が起きるかというと、呼び出すコモンEv内にウェイトが存在する場合、処理が停止している間にコモンセルフ変数が上書きされてしまうわけです。

実験

マップEvを2つ用意して、今回作成したコモンEv[キャラ退室&移動]を以下の通り引数(入力の値)を変えて呼び出してみます。


コモンEv[キャラ退室&移動]で以下のようなデバッグ文を表示させると...

上書きが発生してますね。


例えウェイトの位置が処理の始めだとしても、引数がある場合は0行目の処理よりも前に実質的に以下のような処理が入る

■変数操作: CSelf0[移動先マップ指定] = (数値1)
■変数操作: CSelf1[EvID指定] = (数値2)
■変数操作: CSelf2[除外するEvID] = (数値3)


結論

複数の並列実行から同時にコモンEvを呼び出す場合、コモンEvの処理途中にウェイトが入るとコモンセルフ変数の上書きが発生してしまう


この仕様を理解した上で結論として解決策としては以下

解決策

前提:並列処理をする以上、ウェイト無しだと処理が重くなるのでウェイトは入れたい


解決策1:
コモンEv内にウェイトを入れるのはあきらめて、マップEv側にウェイトを入れる

デメリット:面倒

解決策2:
コモンEv内にウェイトを入れる場合は以下のタイミング
引数が無い場合 処理の始め(0行目)
戻り値が無い場合 処理の終わり(イベント処理中断直前にも)
引数も戻り値もある場合 戻り値を工夫(後述)した上で処理の終わり

戻り値を工夫

処理の終わりにウェイトを入れてもコモンセルフ変数が上書きされるので、戻り値(結果の値)に影響してしまう。
ならば、ウェイトを入れる前に戻り値を別の場所(任意の変数)に格納してやればいいやという発想


今回はマップEvから呼び出す前提なので、引数(入力の値)も工夫してマップEvセルフ変数に直接格納してしまいましょう。
(他にも可変DBに格納する手段もありますが戻り値のためだけに使うのはもったいないので)


引数(入力の値)でマップEvセルフ変数を指定可能に。


マップEv側は格納先にセルフ変数0番を指定。



呼出し元のマップEvセルフ変数X変数呼び出しを利用して、
1100000+X
で呼び出せるので、先に格納してしまえばウェイトを入れられるわけです。

データを呼ばない/X番の変数呼出を使用


これで問題なく動作します。


処理の途中にウェイトを入れる場合

処理の都合上、どうしても途中にウェイトを入れる場合、以下の通りその都度可変DBに格納すれば確かに実現できそうです。

同じコモンで複数の情報を同時に処理する場合、 情報を格納するCDBを作って、逐一
CDBから情報を呼び出し→ 処理 → CDBに情報を格納 → 次の対象の情報をCDBから呼び出し → 処理 → ......
という手順を踏む必要がある
つってもウェイトを挟まずに出力するならそんなことしなくて良いけど


1.可変DBに格納用のDBを新規作成

2.コモンイベントで以下を行う
 2-1.変数操作+:(コモンセルフ変数)=呼び出し元マップイベントID
 2-2.可変DB書き込み:[(可変DBID):(コモンセルフ変数):0]=(任意の数字)