今回は、イベントの位置を初期化する方法を3つ紹介します。以前リクエストをいただいた内容です。
イベントの初期化が必要になる例として、石を押して色の違うタイルに乗せるパズルイベントがあります。石を誤った場所に移動すると、タイルの上に乗せられなくなり、詰んでしまうことがあります。

このような場合は、石の位置を初期化する必要があります。
もう1つの例は、敵に追いかけられて捕まるとミスになるイベントです。捕まったあとにプレイヤーと敵イベントの位置を初期化すれば、スタート位置からやり直せます。

どの方法が優れているというわけではありません。制作しているゲームや用途に合わせて選んでください。
1. 場所移動を使う方法

最も簡単なのは、場所移動を使う方法です。
RPGツクールMZには、一度別のマップに移動してから元のマップへ戻ると、イベントの位置が初期化されるという性質があります。
たとえば、街のマップでモブキャラが動いていても、一度建物に入ってから街へ戻ると、モブキャラは最初の位置に戻っています。この挙動を利用します。
基本的な手順
- 「リセット用」などの名前で、新しいマップを作成します。中身は空で問題ありません。
- イベントコマンドの「場所移動」を設定します。
- 最初にリセット用マップのどこかへ移動します。
- そのあと、元のマップのスタート位置へ移動します。向きは下などに設定します。
- 場所移動の前後に「画面のフェードアウト」と「画面のフェードイン」を挟みます。プレイヤーが一瞬見えてしまうのを防ぐためです。
注意点: 同じマップ内で場所移動しただけでは、イベントの位置はリセットされません。必ず一度別のマップへ移動してから戻す必要があります。

変数で移動先を指定する
場所移動の座標を直接指定すると、同じイベントを別のマップで使い回すときに手間がかかります。
たとえば、テスト1のマップ用に作ったイベントをテスト2へコピーすると、移動先はテスト1のままです。この問題は、変数で移動先を指定することで解消できます。
- マップID、X、Yの3つの変数を用意します。
- マップに入ったとき、自動実行で初期位置を取得するイベントを作ります。
- マップIDに「ゲームデータ → マップID」を代入します。
- Xに「キャラクター → プレイヤーのマップX」を代入します。
- Yに「キャラクター → プレイヤーのマップY」を代入します。
- 最後に「イベントの一時消去」で自身を消します。
- 位置をリセットするときの場所移動先に、これらの変数を指定します。
イベントの一時消去には、一度マップを出てから戻るとイベントが復活する性質があります。そのため、マップに入るたびに初期位置が上書きされます。

この仕組みを利用すると、ステージ1・2・3があるミニゲームで、ステージ2でミスした場合はステージ1ではなくステージ2から再開する、といった簡易的なオートセーブも実現できます。
2. イベント位置の設定を使う方法
2つ目は、イベントコマンド2ページ目の「イベント位置の設定」を使い、イベントを直接動かす方法です。
場所移動ではプレイヤーを別の場所へ移動させます。一方、イベント位置の設定では、指定したイベントを同じマップ内の別の座標へ移動できます。
プレイヤーは移動しないため、リセット用マップも必要ありません。

座標を直接指定する
戻したいイベントごとに「イベント位置の設定」を使い、元の座標を直接指定します。
変数で座標を指定する
イベントごとにX・Yの変数を用意し、初期位置を取得するイベントで、各イベントのマップXとマップYを変数へ代入しておきます。リセット時は、その変数を参照してイベントを移動させます。
この方法の弱点は、各イベントのX・Y座標を取得するために、多くの変数が必要になることです。イベントが3つだけでも、X・Y × 3で合計6つの変数を使います。石が4つ、5つと増えると管理が大変です。

解決策として、セルフ変数を使えるプラグインを利用する方法もあります。ただし、余計なバグやメンテナンスの手間を減らすためにも、できればプラグインの数は増やしたくないところです。
3. スクリプトで位置を初期化する方法
3つ目は、変数やイベント位置の設定を使わず、スクリプトでイベントを一括初期化する方法です。
メモ欄で対象イベントを指定する
イベントのメモ欄に `<ターゲット>` と書きます。これにより、メモ欄に「ターゲット」と書かれたイベントだけを元の位置へ戻し、それ以外のイベントは動かさないように制御できます。
メモ欄へ任意の文字を入れるときは、`<>`という不等号の中に文字を入れることを覚えておいてください。

スクリプトの内容
イベントコマンド3ページ目にある、上級の「スクリプト」へ以下を入力します。
for (let i = 1; i < $gameMap._events.length; i++) {
if (!!$gameMap._events[i]) {
if ($gameMap._events[i].event().note.match(/<target>/)) {
$gameMap._events[i].locate(
$gameMap._events[i].event().x,
$gameMap._events[i].event().y
);
}
}
}スクリプトの仕組み
コードを見るだけで頭が痛くなる方もいるかもしれません。僕も頭が痛くなりますが、処理を分けて見れば理解しやすくなります。
for文でイベントを順番に処理する
- `let i = 1`:変数iに1を代入し、イベントID 1から開始します。
- `i <= $gameMap._events.length`:iがマップ内のイベント最大数以下である間、ループします。
- `i++`:ループを1周するたびに、iへ1を加えます。
つまり、イベントID 1から最大番号まで、順番に処理を実行しています。
1つ目のif文でイベントの存在を確認する
`!!$gameMap._events[i]`では、イベントID iのイベントがマップに存在するかを確認します。
RPGツクールでイベントを作っていると、ID 5を削除してID 7だけが残るようなことがあります。存在しないイベントを処理するとエラーになるため、ここでスキップします。
2つ目のif文でメモ欄を確認する
`$gameMap._events[i].event().note.match(‘target’)`では、メモ欄に「target」という文字があるかを判定します。
スクリプト内で文字列を参照するときは、シングルクォーテーション(’)またはダブルクォーテーション(”)で囲みます。
locateで初期位置へ移動する
- `$gameMap._events[i].event().x`:イベントの初期X座標を自動参照します。
- `$gameMap._events[i].event().y`:イベントの初期Y座標を自動参照します。
イベントの初期位置を変更すると、参照する座標も自動的に変わります。そのため、イベントを増やしたり別の場所へ移動したりしても、このスクリプト1つで初期化できることが最大の利点です。

4. セルフスイッチも一緒にリセットする
イベントによっては、位置だけでなくセルフスイッチもリセットする必要があります。
たとえば、ゴールのリージョンに到達するとセルフスイッチAがオンになり、イベントが2ページ目へ移行して動かなくなる仕様を考えてみます。この場合、位置だけを初期化しても、イベントは2ページ目のままなので、押しても動きません。
このような場合は、イベントの位置を初期化するときに、セルフスイッチAも同時にオフにします。
セルフスイッチAをオフにする
スクリプトのターゲット判定のあとに、以下を追加します。
$gameSelfSwitches.setValue([this._mapId, i, 'A'], false);- `this._mapId`:現在のマップIDです。
- `i`:ループ中のイベントIDです。
- `’A’`:オフにするスイッチのアルファベットです。
- `false`:オフを表します。オンにする場合は `true`です。

A〜Dをまとめてオフにする
セルフスイッチA・B・C・Dを複数使っている場合、1つずつ書くとコードが長くなります。そこで、配列とfor…of文を使います。
const arr = ['D', 'C', 'B', 'A'];
for (let i = 1; i <= $gameMap._events.length; i++) {
if (!!$gameMap._events[i]) {
if ($gameMap._events[i].event().note.match('ターゲット')) {
$gameMap._events[i].locate(
$gameMap._events[i].event().x,
$gameMap._events[i].event().y
);
for (const val of arr) {
$gameSelfSwitches.setValue([this._mapId, i, val], false);
}
}
}
}- `const arr = [‘D’, ‘C’, ‘B’, ‘A’]`:配列にD・C・B・Aを格納します。
- `for (const val of arr)`:配列の中身を順番にvalへ入れてループします。
- この処理だけで、セルフスイッチD・C・B・Aをすべてオフにできます。

慣れていないと少し難しく感じるかもしれません。必要になったときは、このコードをそのままコピーして貼り付けても問題ありません。
まとめ
| 方法 | 特徴 | 向いている場面 |
|---|---|---|
| 場所移動 | 最も簡単。別マップを1つ用意するだけ | シンプルなリセットが必要な場面 |
| イベント位置の設定 | プレイヤーは移動しない。変数が増えやすい | イベント数が少ない場合 |
| スクリプト | メモ欄で対象を指定。変数が不要で拡張性が高い | イベント数が多い場合や、使い回したい場合 |
- 場所移動で位置をリセットする場合は、必ず別のマップを経由します。同じマップ内の移動ではリセットされません。
- 変数で移動先を指定すると、コピーしやすく、メンテナンスも楽になります。
- スクリプトでは `$gameMap._events[i].event().x`と`$gameMap._events[i].event().y`で、初期座標を自動参照できます。
- 必要な場合は、セルフスイッチのリセットも忘れずに行います。
変数を使った場所移動やメモ欄の参照方法は、ドラクエのルーラ・リレミト再現の回でも解説しています。スクリプトの基礎は、スクリプト入門の回で詳しく紹介しています。必要に応じて、そちらも試してみてください。

