今回はワールドマップをユニティちゃんが歩いている時に敵と遭遇するという機能を作成していきたいと思います。
前回はユニティちゃんが動いていない時にパーティーメンバーのステータスを表示する機能を作成しました。
ユニティちゃんのRPGを作ってみようの他の記事は
から見ることが出来ます。
以前、ワールドマップ上に敵キャラクターを配置しておき、敵と接触したら戦闘シーンに移動するという機能を作成しました。
その時は敵を予め配置しておくという事をやりましたが、今回はワールドマップに敵キャラクターを置かずにスクリプトでエンカウント機能(敵と遭遇する機能)を作成したいと思います。
今回やる事は一定時間内のランダムな時間を設定し、ユニティちゃんが歩いている時だけ時間を計測しその時間になったら敵と遭遇するようにするという機能だけを作ります。
敵と遭遇したら敵との戦闘シーンへと移行しますが、戦闘シーンに関しては次の記事以降で作成していきます。
WorldMapシーンにエンカウント機能を取り付ける
WorldMapシーンを開きヒエラルキー上で右クリックしてCreate Emptyを選択し、名前をEncountManagerとします。
Assets/RPG/Scriptsフォルダ内に新しくEncountManagerスクリプトを作成し、EncountManagerゲームオブジェクトにドラッグ&ドロップして取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class EncountManager : MonoBehaviour { // LoadSceneManager private LoadSceneManager sceneManager; [SerializeField] private float encountMinTime = 3f; // 敵と遭遇するランダム時間 [SerializeField] private float encountMaxTime = 30f; // 経過時間 [SerializeField] private float elapsedTime; // 目的の時間 [SerializeField] private float destinationTime; // ユニティちゃん private Transform unityChanObjct; // ユニティちゃんスクリプト private UnityChanScript unityChanScript; // Start is called before the first frame update void Start() { sceneManager = GameObject.Find("SceneManager").GetComponent<LoadSceneManager>(); SetDestinationTime(); unityChanObjct = GameObject.FindWithTag("Player").transform; unityChanScript = unityChanObjct.GetComponent<UnityChanScript>(); } // Update is called once per frame void Update() { // 移動していない時は計測しない if (Mathf.Approximately(Input.GetAxis("Horizontal"), 0f) && Mathf.Approximately(Input.GetAxis("Vertical"), 0f) ) { return; } // ユニティちゃんが何らかの行動をしていたら計測しない if(unityChanScript.GetState() == UnityChanScript.State.Talk || unityChanScript.GetState() == UnityChanScript.State.Command ) { return; } elapsedTime += Time.deltaTime; if(elapsedTime >= destinationTime) { Debug.Log("遭遇"); sceneManager.GoToNextScene(SceneMovementData.SceneType.WorldMapToBattle); elapsedTime = 0f; SetDestinationTime(); } } // 次に敵と遭遇する時間 public void SetDestinationTime() { destinationTime = Random.Range(encountMinTime, encountMaxTime); } } |
EncountManagerスクリプトは非常にシンプルでインスペクタでencountMinTime(最小時間)とencountMaxTime(最大時間)を設定出来るようにしています。
SetDestinationTimeメソッドが呼ばれるとRandom.Rangeメソッドを使ってencountMinTimeとencountMaxTimeの間でランダムな値を取得し、その時間をdestinationTimeに入れます。
UpdateメソッドではMathf.Approximatelyを使って移動値が0に限りなく近い場合はそれ以降の処理は何もしません。
またユニティちゃんが何らかの行動、例えばアイテムを使用しようとコマンド画面を開いている時等は時間計測をしないようにします。
それ以外の時はelapsedTimeに時間を足していき、目的の時間を越えたらLoadSceneManagerのGoToNextSceneメソッドを呼び出し戦闘シーンへと遷移させます。
SceneMovementDataスクリプトに追記する
SceneMovementDataスクリプトのSceneTypeにWorldMapToBattleを追加します。
1 2 3 4 5 6 7 8 | public enum SceneType { StartGame, FirstVillage, FirstVillageToWorldMap, WorldMapToBattle } |
また、FadeAndLoadSceneメソッドでSceneTypeがWorldMapToBattleの時にBattleシーンへと遷移する処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // フェードをした後にシーン読み込み IEnumerator FadeAndLoadScene(SceneMovementData.SceneType scene) { // フェードUIのインスタンス化 fadeInstance = Instantiate<GameObject>(fadePrefab); fadeImage = fadeInstance.GetComponentInChildren<Image>(); // フェードアウト処理 yield return StartCoroutine(Fade(1f)); // シーンの読み込み if (scene == SceneMovementData.SceneType.FirstVillage) { yield return StartCoroutine(LoadScene("Village")); } else if (scene == SceneMovementData.SceneType.FirstVillageToWorldMap) { yield return StartCoroutine(LoadScene("WorldMap")); } else if(scene == SceneMovementData.SceneType.WorldMapToBattle) { yield return StartCoroutine(LoadScene("Battle")); } |
Battleシーンの作成と設定
敵と遭遇したら戦闘シーンへと遷移させるようにスクリプトを作ったのでAssets/RPG/Scenesフォルダに新しくBattleシーンを作成します。
Battleシーンを作成したらUnityメニューのFile→Build SettingsにBattleシーンをドラッグ&ドロップして登録しておきます。
ワールドマップから戦闘シーンへの遷移を確認する
機能が出来たので、ワールドマップでユニティちゃんを動かして敵と遭遇し、Battleシーンへと遷移するかどうかを確認します。
上のようになりました。
シーンの遷移は以前作成した村→ワールドマップ、ワールドマップ→村の遷移の時と同じように画像の透明度を操作したフェードを行っています。
戦闘シーンに遷移する時だけは別のフェードを使いたいので、それはまた別の記事で作ります。
この作品はユニティちゃんライセンス条項の元に提供されています