敵とゲージをまとめて管理してみました。敵を作るとゲージも作られて敵が持ちます。
Canvasをシーンに置いて、Imageのプレハブを作りました。CanvasはUI Scale ModeをScale Wit Screen Sizeにします。
Imageにはスクリプトを付けます。
このスクリプトには表示位置と色を変えるメソッドがあります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Gauge : MonoBehaviour
{
RectTransform rt;
private void Awake()
{
rt = GetComponent<RectTransform>();
}
// Start is called before the first frame update
void Start()
{
}
// 表示位置をセット
public void SetPosition(float x, float y)
{
Vector2 pos = rt.anchoredPosition;
pos.x = x;
pos.y = y;
rt.anchoredPosition = pos;
}
// 色を変える
public void ChangeColor(Color color)
{
Image image = GetComponent<Image>();
image.color = color;
}
}
オブジェクトを登録管理するの敵のクラスにゲージを作るメソッドを作ります。インスタンス化したゲージはプロパティに入れて置きます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityStandardAssets.Characters.FirstPerson;
public class TestAgent : MonoBehaviour
{
NavMeshAgent agent;
// ゲージ
public Gauge Gauge{ get; private set; }
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
GoNextPoint();
}
// Update is called once per frame
void Update()
{
if (!agent.pathPending && agent.remainingDistance < 0.5f)
{
GoNextPoint();
}
ChangeGaugePosition();
}
// ゲージを位置を変える
void ChangeGaugePosition()
{
// 敵の位置
Vector3 dir = transform.position;
// プレイヤーと敵の高さを合わせる
dir.y = FirstPersonController.GetInstance().transform.position.y;
// 敵からプレイヤーへの方向
dir -= FirstPersonController.GetInstance().transform.position;
// 方向ベクトルをプレイヤーに合わせて回転
dir = Quaternion.Inverse(FirstPersonController.GetInstance().transform.rotation) * dir;
// ベクトルの長さを制限
dir = Vector3.ClampMagnitude(dir, 100f);
// ゲージの位置をセット
Gauge.SetPosition(dir.x * 8f, dir.z * 8f);
}
// 次の目的地を設定
void GoNextPoint()
{
agent.destination = TestAgentFactory.GetInstance().GetRandomPoint().position;
}
// 大きくなる
public void Bigger()
{
Vector3 scale = transform.localScale;
scale *= 2f;
transform.localScale = scale;
}
// 小さくなる
public void Smaller()
{
Vector3 scale = transform.localScale;
scale *= 0.5f;
transform.localScale = scale;
}
// ゲージを作る
public void CreateGauge(Gauge gaugePrefab, Canvas canvas, Color color)
{
// ゲージが無いとき
if(Gauge == null)
{
Gauge = Instantiate(gaugePrefab.gameObject, canvas.transform).GetComponent<Gauge>();
Gauge.ChangeColor(color);
ChangeGaugePosition();
}
}
// 破壊
public void Destroy()
{
Destroy(Gauge.gameObject);
Destroy(gameObject);
}
}
また、Updateでプレイヤーの位置に応じてゲージの表示位置を変えています。自分自身とゲージのオブジェクトを破壊するメソッドも作りました。
そして、敵の管理クラスで敵を作ると、その敵のスクリプトのゲージを作るメソッドを呼びます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestAgentFactory : MonoBehaviour
{
static TestAgentFactory instance;
public static TestAgentFactory GetInstance()
{
return instance;
}
[SerializeField] Transform points;
[SerializeField] TestAgent spherePrefab;
[SerializeField] TestAgent cubePrefab;
[SerializeField] TestAgent capsulePrefab;
Dictionary<string, TestAgent> agents = new Dictionary<string, TestAgent>();
public Dictionary<string, TestAgent> GetAgents()
{
return agents;
}
[SerializeField] Gauge gaugePrefab;
[SerializeField] Canvas canvas;
public void RemoveAgent(string agentName)
{
if(agents.ContainsKey(agentName))
{
// 敵とゲージを破壊
agents[agentName].Destroy();
// 辞書から削除
agents.Remove(agentName);
}
}
private void Awake()
{
instance = this;
}
// 目的地をランダムで返す
public Transform GetRandomPoint()
{
return points.GetChild(Random.Range(0, points.childCount));
}
public TestAgent GetAgent(string agentName)
{
// すでにあるとき
if(agents.ContainsKey(agentName))
{
// 辞書にあるものを返す
return agents[agentName];
}
// 無い時
else
{
TestAgent agentPrefab;
Color color;
// プレハブを選択
switch(agentName)
{
case "sphere":
case "Sphere":
agentPrefab = spherePrefab;
color = Color.blue;
break;
case "cube":
case "Cube":
agentPrefab = cubePrefab;
color = Color.yellow;
break;
case "capsule":
case "Capsule":
agentPrefab = capsulePrefab;
color = Color.red;
break;
default:
return null;
}
// 出現ポイントをランダムで選ぶ
Transform point = GetRandomPoint();
// インスタンス化
TestAgent testAgent = Instantiate(agentPrefab.gameObject, point.position, point.rotation).GetComponent<TestAgent>();
// ゲージを作る
testAgent.CreateGauge(gaugePrefab, canvas, color);
// 辞書に登録
agents.Add(agentName, testAgent);
// 返す
return testAgent;
}
}
}
敵を削除するときは、敵のスクリプトの破壊メソッドを呼んで、辞書から削除します。