//tips
//EnemyAIの生成
フィールド上に配置したEnemyAIを動かすことはできたので、今度はEnemyAIをランダム生成して動かしていく。
まずはシーン上のオブジェクトをprefab化する。そして空オブジェクトでEnemyAIの生成場所になるオブジェクトを作成し、下記スクリプトをアタッチ。このスクリプトで空オブジェクトの場所からEnemyAIを任意の数、任意のタイミングで生成することができる。
using UnityEngine;
using System.Collections;
public class AppearScript : MonoBehaviour
{
// 出現させる敵の格納
[SerializeField] GameObject[] enemys;
// 出現時間
[SerializeField] float appearNextTime;
// 生成可能数
[SerializeField] int maxNumOfEnemys;
// 生成総数
private int numberOfEnemys;
// 次弾待機計測
private float elapsedTime;
void Start()
{
numberOfEnemys = 0;
elapsedTime = 0f;
}
void Update()
{
// この場所から出現する最大数を超えてたら何もしない
if (numberOfEnemys >= maxNumOfEnemys)
{
return;
}
// 経過時間を足す
elapsedTime += Time.deltaTime;
// 経過時間が経ったら
if (elapsedTime > appearNextTime)
{
elapsedTime = 0f;
AppearEnemy();
}
}
// 敵出現メソッド
void AppearEnemy()
{
// 出現させる敵をランダムに選ぶ
var randomValue = Random.Range(0, enemys.Length);
// 敵の向きをランダムに決定
var randomRotationY = Random.value * 360f;
GameObject.Instantiate(enemys[randomValue], transform.position, Quaternion.Euler(0f, randomRotationY, 0f));
numberOfEnemys++;
elapsedTime = 0f;
}
}
これでEnemyAIのスポーンポイントを生成できた。EnemyAIが突如出現するのは怖いので、エフェクトにより出現タイミングがわかるようにする。
Standard AssetsのParticleプレファブをインスペクターに設置する。設置用スクリプトは下記。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class appearEffect : MonoBehaviour
{
// 出現エフェクト
[SerializeField]
private GameObject effectObject;
// 消滅秒数
[SerializeField]
private float deleteTime;
// 出現位置のオフセット
[SerializeField]
private float offset;
void Start()
{
// ゲームオブジェクト登場時にエフェクトをインスタンス化
var instantiateEffect = GameObject.Instantiate(effectObject, transform.position + new Vector3(0f, offset, 0f), Quaternion.identity) as GameObject;
Destroy(instantiateEffect, deleteTime);
}
}
Prefab生成するEnemyAIにもHP表示をつけさせたいので、そちらの仕組みも加えていく。一旦以前作成したcanvasとその子要素にスライダー一式を持つUIHPprefabをアタッチ。
こうするとcanvasのrendermodeのEventcameraがnoneになってしまう。以前は入れ子でUIを作ることでこの問題を回避したが今回は別の方法を見つけたので試していく。
参考にするのはこちらのUnityの回答。
https://answers.unity.com/questions/995400/gui-canvas-worldspace-camera-not-copied-into-prefa.html
canvas.GetComponent<Canvas> ().worldCamera = Camera.main;とすることでこのEventcameraのnoneの部分にシーンのカメラをはめ込むことができるよう。
下記スクリプトを試しに、EnemyAIprefabのHPUIオブジェクトにアタッチしてみた。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HPUICreateCanvas : MonoBehaviour
{
public GameObject myCanvas;
void Start()
{
GameObject canvas = Instantiate(myCanvas) as GameObject;
canvas.GetComponent<Canvas>().worldCamera = Camera.main;
}
}
そうすると無限にHPUIが生成されるバグになってしまった。これはinstantiateしたcanvasにアタッチしたオブジェクトにinstantiateをする指示を埋め込んだためと考えられる。
Cameraのセット自体はできたので、その部分だけ適応させられるように考える。また爆発の出現エフェクトは特に必要ないかと思い外すことにした。
そもそもInstantiateする必要がなかったので下記に修正することで無事に解決した。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HPUICreateCanvas : MonoBehaviour
{
public GameObject myCanvas;
void Start()
{
//GameObject canvas = Instantiate(myCanvas) as GameObject;
myCanvas.GetComponent<Canvas>().worldCamera = Camera.main;
}
}
HPバーは表示できたがそもそものEnemyのHP設定はしていないのでプレイヤーのものを参考に新たに作成する。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HPScriptE : MonoBehaviour
{
[SerializeField]
private float maxHp = 3; //体力
[SerializeField]
public float hp;
// HP表示用UI
[SerializeField]
private GameObject HPUI;
// HP表示用スライダー
private Slider hpSlider;
void Start()
{
hpSlider = HPUI.transform.Find("HPBar").GetComponent<Slider>();
hpSlider.value = 1f;
}
void Update()
{
hpSlider.value = hp / maxHp;
if (hp <= 0)
{
// HP表示用UIを非表示にする
HideStatusUI();
}
}
//HPUIを非表示にする
public void HideStatusUI()
{
HPUI.SetActive(false);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Weapon")
{
Debug.Log("hit Player");
Debug.Log("hit Damage");
hp -= other.gameObject.GetComponent<rodManager>().powerEnemy;
//hp -= other.gameObject.GetComponent<rodManager>().powerEnemy;
}
//体力が0以下になった時{}内の処理が行われる
if (hp <= 0)
{
Destroy(gameObject); //ゲームオブジェクトが破壊される
}
}
}
これによりプレイヤーのweaponにより干渉を受けるHPバーを持ったEnemyAIが徘徊するようになった。プレイヤーの武器とUIも整えて交戦できるようにする。