【Unity】敵とゲージをまとめて管理する

投稿者: | 2021-01-06

敵とゲージをまとめて管理してみました。敵を作るとゲージも作られて敵が持ちます。

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;
        }
    }

}

敵を削除するときは、敵のスクリプトの破壊メソッドを呼んで、辞書から削除します。

コメントを残す

メールアドレスが公開されることはありません。