part1
・playerの攻撃を作成(当たり判定なし)までを解説
part2
・playerの常時ステータス表示windowとステータスバー(Hp,MP)までを解説
part3
・敵にHpとGoldを付与して、敵用のHpバーも作成するまでを解説
part4
・敵への攻撃判定までを実装するまでを解説
part5
・playerの攻撃の種類を増やして複数攻撃を実装までを解説
part6
・敵のAIや表示UIの調整から完成まで!!(最終回)
この講座を最後まで呼んでいただけると出来るゲームの内容(このゲームようなアクションRPGをつくります)
⇒ALL YOU NEED IS GOLD 0
さて、前回part2まででplayerのHPバーまでを実装してきました。今回part3では Uniteのイベントシステムを利用して、マップをランダムに徘徊する敵を作成(最終的には敵はある距離からは playerを追跡するAIを実装しますが、それは後のpartで解説しますね!)します。そして、 その敵に固有のHPと敵を倒したときに手に入るGoldを設定して、敵のHPバーが表示されるところまでを このpart3では実装していきます。今回でUniteで一番使うであろうEventシステムにコードから 介入する方法をマスターしましょう!!
まずはマップにEventを作成してください。以下の画像を参考にしてください。
重要な所は赤で印をつけております。イベントの場所はどこでもいいです。
イベントの名前は分かりやすいものならなんでもいいです。そして「メモ」!!これは超重要!!ってか
あって良かったとおもう部分。ここに今回は「gorotuki」と記載しておりますが、これはあとで
コードから参照するので正確に入力してください。
このメモ欄を利用して、敵の種類に報じてHpやGoldを設定することができます。これはとても便利というか
これが無かったらどうするのかな?
後は画像は任意の画像、移動はランダム、トリガーはイベントから接触としてください。これでゲームを
起動すると作成した敵が画面を徘徊するはずです。
さて、これで敵が歩き回るようになりました。つづいて敵にHpやGoldといった
パラメーターを付与しましょう。playerではUniteの既存のシステムのHpを参照しました。これは
playerは今後成長したりするし、またゲーム途中でセーブ等するのでUniteのパラメーターを
そのまま参照した方が、Uniteで提供されているsave機能をそのまま仕様できるからです。
unityはsave機能が正直使いにくいので、自分でゲームを作成するときは自作のスクリプトを
使用していましたが、かなり面倒だったのでなにげに、初めからsave機能が提供されている
のもUniteのかなり良いところですよね!
しかし、今回の敵では完全にオリジナルのパラメーターを付与することにします。
ゲームを起動してSceneMapをみていると、New Game objectが増えていますね。これらが
新しく作成したEventです。Eventのインスペクターを見ていきましょう。するとEventには
playerと同様いくつかのscriptがアタッチされています。今回はこの中のEventOnmapを見てみましょう。
このEventOnMapはplayerについていたActorOnMapと同様にCharacterOnMapを継承しています。
このEventOnMapを介してscriptからEventに様々な命令をを出したり、Eventの変数を参照できます。
開発後の画像なので、一部ここまで進めた状態とは異なります。
まずはEventOnMapが継承しているCharaterOnMapに変数を加えます。これはEventOnMapに加えても どっちでもいいです。
//以下改変-----------------------------------------------------------------------------------------------------
public int my_EnemyHp;
public int my_EnemyGold;
//----------------------------------------------------------------------------------------------------以下改変
上記コードをcharacterOnMapの冒頭、変数宣言部分で宣言してください。これでゲームを起動してEventOnMapのインスペクターを確認すると ちゃんと宣言されています。後はここに指定したHpやGoldを付与すればいいですね。
開発後なのですでにHp,Goldが付与されています。ここまでの状態であればともに0となっています。
さて、それでは前回作成したMy_Eventmanagerスクリプトを以下の様に変更してください
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//eventonmap
using RPGMaker.Codebase.Runtime.Map.Component.Character;
//mapeventexcutioncontroller
using RPGMaker.Codebase.Runtime.Map;
public class My_EventManager : MonoBehaviour
{
private My_PlayerManagerScript my_PlayerManagerScript;
private GameObject player;
public Canvas my_PlayerCanvas;
private My_PlayerCanvasScript my_PlayerCanvasScript;
//eventonmap
private List<EventOnMap>eventOnMaps;
//playrのオブジェクトをstartで取得するとnullのエラーがでるのでこれを挟む
//またmap移動したときにplayerも破棄されるので再度initするためのフラグにしている
private bool first;
// Start is called before the first frame update
void Start()
{
first = false;
my_PlayerManagerScript = this.gameObject.GetComponent<My_PlayerManagerScript>();
}
// Update is called once per frame
void Update()
{
EventManagerInitProcess();
if(player != null)
{
if(CheckPlayerStatusChange())
{
SetPlayerStatus();
}
}
}
//startで呼ぶとうまくいかないのでこちらでEvent関連を初期化
public void EventManagerInitProcess() {
if (first == false)
{
if (Camera.main != null)
{
player = my_PlayerManagerScript.GetPlayerObject();
InitPlayerCanvas(player);
//このタイミングで敵EVENTの初期化
EnemyMapEventInit();
first = true;
}
}
else if (first == true)
{
if (player == null)
{
Debug.Log("player lost");
//Mapが切り替わっているので初期化を呼ぶためフラグをfalse
first = false;
}
}
}
//playerのcanvasの初期化
public void InitPlayerCanvas(GameObject player) {
Canvas my_PlayercanvasPrefab = Instantiate(my_PlayerCanvas);
my_PlayercanvasPrefab.transform.SetParent(player.transform, false);
my_PlayerCanvasScript = my_PlayercanvasPrefab.GetComponent$lt;My_PlayerCanvasScript>();
//MaxHp,Hp設定
my_PlayerCanvasScript.playerMaxHp = my_PlayerManagerScript.GetPlayerMaxHp();
my_PlayerCanvasScript.playerHp = my_PlayerManagerScript.GetPlayerHp();
//Mp設定
my_PlayerCanvasScript.playerMaxMp = my_PlayerManagerScript.GetPlayerMaxMp();
my_PlayerCanvasScript.playerMp = my_PlayerManagerScript.GetPlayerMp();
//playerスライダーの初期化
my_PlayerCanvasScript.InitPlayerSlider();
Debug.Log("player init!");
}
//eventで作成している敵の初期化
public void EnemyMapEventInit() {
Debug.Log("my_controll start");
//全てのマップにあるイベントを取得
eventOnMaps = MapEventExecutionController.Instance.GetEvents();
Debug.Log("eventCount: " + eventOnMaps.Count);
for (int i = 0; i < eventOnMaps.Count; i++)
{
//noteの内容で出来の処理の初期化を分岐
if (eventOnMaps[i].MapDataModelEvent.note == "gorotuki")
{
//EVENTにHPとGLODを付与
EnemyEventInitProcess(i, 5, 15);
}
}
}
// EnemyMapEventInit()で仕様される共通の部分
public void EnemyEventInitProcess(int i, int hp, int enemyGold) {
eventOnMaps[i].my_EnemyHp = hp;
eventOnMaps[i].my_EnemyGold = enemyGold;
}
//以下略
}
まずは冒頭でusingでパスを通してください。コメントしていますが、EventOnMapとMapEventExecutionControllerを
参照するためです。EventManagerInitProcess()関数の中でEnemyMapEventInit()を呼んで初期化します。
初期化はEnemyMapEventInit()関数で実際に行っています。
eventOnMaps = MapEventExecutionController.Instance.GetEvents()
上記でMAPの全てのEVENTが取得できます。とても便利で簡単です。そしてeventOnMapsは
private List<EventOnMap>eventOnMaps;
上記で宣言しているようにlistなのでfor分で全部参照します。そしてEVENTのメモの部分に「gorotuki」の
キーワードがあったら、そのEVNETのhpとgoldの変数に指定した値を代入すればいいですね。
eventOnMaps[i].MapDataModelEvent.note == "gorotuki"
上記の部分でメモの部分を参照しています。そして、今後敵が増えると使いまわす処理なので実際にhpとGoldを
代入する処理は関数化してEnemyMapEventInit()に移しています。
これでゲームを起動すると変数に指定の値が代入されているはずです。
さてpart3最後の部分です。敵にHpもGoldも付与できましたので、このHpに連動した敵用のHpバーを 作成しましょう。作成自体は簡単です、My_playerCanvasを利用すればいいですね。 My_PlayerCanvasをプレハブからヒエラルキー部分に出して、右クリックから全てを展開を選んでください。これで プレハブとの関係は切れます。(つまり今ヒエラルキーにあるMy_PlayerCanvasを変更してもプレハブに 影響しません)そして、名前をMy_EnemyCanvasにしてください。そしてMpバーは不要なのでこれを削除してください。 そしてこのMy_EnemyCanvasを管理するMy_EnemyCanvasScriptを作成してアタッチしてください。 ここまで出来たら、プレハブ化してください。
プレハブ化が出来たら、My_EnemyanvasScriptを以下の様に記載してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class My_EnemyCanvasScript : MonoBehaviour
{
//My_EnemyCanvasのHpスライダーをアタッチしてください
public Slider enemyHpSlider;
public int enemyMaxHp;
public int enemyHp;
//Canvas参照用
private Canvas enemyCanvas;
//キャンバス初期化
public void InitEnemyHpSlider() {
enemyCanvas = gameObject.GetComponent<Canvas>();
enemyCanvas.worldCamera = Camera.main;
enemyHpSlider.maxValue = enemyMaxHp;
enemyHpSlider.value = enemyHp;
}
public void setEnemyHp() {
if (enemyHp <= 0)
{
enemyHp = 0;
}
enemyHpSlider.value = enemyHp;
}
}
ここまでできれば、My_EnemyCanvasのインスペクターは以下の様になっています。
これで下準備はできたので、My_EventMangaerを改造していきましょう。変更部分示します。
まずは以下を宣言
//enemyCanvas
public Canvas my_EnemyCanvas;
このmy_Enemyanvasに先ほど作成してプレハブ化したMy_EnemyCanvasをアタッチしてください。
残りの変更点はEnemyEventInitProcess()の中なので、以下に示します。
public void EnemyEventInitProcess(int i, int hp, int enemyGold) {
//Hp設定
eventOnMaps[i].my_EnemyHp = hp;
//Gold設定
eventOnMaps[i].my_EnemyGold = enemyGold;
//ターゲットのEVENTのgameObjectをイベントIDから取得
GameObject targetObject = MapEventExecutionController.Instance.GetEventMapGameObject(eventOnMaps[i].MapDataModelEvent.eventId);
//取得したゲームオブジェクトの子オブジェクトにプレハブのenemycanvasを入れる
Canvas enemyCanvasPrefub = Instantiate(my_EnemyCanvas);
enemyCanvasPrefub.transform.SetParent(targetObject.transform, false);
//enemyのHPの初期化 my_EnemyCanvasScriptはそれぞれ必要なのでその分用意
My_EnemyCanvasScript my_EnemyCanvasScript = enemyCanvasPrefub.GetComponent<My_EnemyCanvasScript>();
//引数で取得したHpとGoldを設定
my_EnemyCanvasScript.enemyMaxHp = eventOnMaps[i].my_EnemyHp;
my_EnemyCanvasScript.enemyHp = my_EnemyCanvasScript.enemyMaxHp;
//sliderも初期化
my_EnemyCanvasScript.InitEnemyHpSlider();
}
やっていることはEVENTのGameObjectを取得して、後はPlayerの時と同様の事をしています。 それでは実行の前に、敵のEVENTをもう一つ適当に作成して、実行してみてください。 (メモをgorotuki以外にしてgorotukiと違うHpを与えてください) それぞれで指定した値のHpとGoldが付与され、きちんと敵用のHpバーが表示されれば完成です。 自分は敵用のHpバーは紫にして、背景は透明にしています。
無事に上記の様な画面が表示されればこのpart3はクリアです!!さてここまで呼んで頂いてありがとうございます! 一緒に作成してくれている方がいるとうれしいです。ここまで来るとだんだんアクションRPGっぽくなってきましたよね! され次回part4では遂に、part1で作成した攻撃が火を吹きます!ついにあたり判定を作成して作成した敵をかっこよく 倒せるようになるまでを解説していきます!part4もよろしくお願いします!!!