【Unity】ミニマップにレーダーで捉えた敵の位置を表示する #2

投稿者: | 2020-06-28

レーダーで捉えた複数の敵をミニマップ上に表示してみます。ミニマップ上の画像の色は敵の色に合わせて変えます。敵の生成や削除もできるようにします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RadarTest : MonoBehaviour
{

    List<AgentScript3> enemys = new List<AgentScript3>();
    [SerializeField] GameObject enemy;
    [SerializeField] Transform player;
    [SerializeField] Image center;
    [SerializeField] Image redDot;
    [SerializeField] GameObject dest;
    Transform[] points;

    List<RectTransform> redDots = new List<RectTransform>();
    [SerializeField] float radarLength = 30f;

    RectTransform[] rt;
    Vector2 offset;
    float r = 6f;
    float s = 0f;

    // Start is called before the first frame update
    void Start()
    {
        GameObject[] objects = GameObject.FindGameObjectsWithTag("Agent");

        foreach (GameObject o in objects)
        {
            AgentScript3 s = o.GetComponent<AgentScript3>();
            s.sc_radar = this;
            s.image = Instantiate(redDot, center.transform.parent).GetComponent<RectTransform>();
            enemys.Add(o.GetComponent<AgentScript3>());
        }

        offset = center.GetComponent<RectTransform>().anchoredPosition;
        points = dest.GetComponentsInChildren<Transform>();
    }    

    // Update is called once per frame
    void Update()
    {
        s += Time.deltaTime;

        // 3秒ごとに敵を削除
        if (s >= 3f)
        {
            s = 0f;

            if(enemys.Count != 0) DestroyEnemy(enemys[Random.Range(0, enemys.Count - 1)]);
        }

        for(int n = 0; n< enemys.Count; n++)
        {

            // Imageがなければ生成
            if(!enemys[n].image) enemys[n].image = Instantiate(redDot, center.transform.parent).GetComponent<RectTransform>();

            Vector3 enemyDir = enemys[n].transform.position;
            enemyDir.y = player.position.y; // プレイヤーと敵の高さを合わせる
            enemyDir = enemys[n].transform.position - player.position;

            enemyDir = Quaternion.Inverse(player.rotation) * enemyDir; // ベクトルをプレイヤーに合わせて回転
            enemyDir = Vector3.ClampMagnitude(enemyDir, radarLength); // ベクトルの長さを制限

            // 赤点の位置を決める
            enemys[n].image.anchoredPosition = new Vector2(enemyDir.x * r + offset.x, enemyDir.z * r + offset.y);
        }      

        if (Input.GetKeyDown(KeyCode.E))
        {
            offset = center.GetComponent<RectTransform>().anchoredPosition;
            InstantiateEnemy(player.transform.position, player.transform.rotation); // 新しい敵を作る
        }

    }


    public void DestroyEnemy(AgentScript3 a)
    {
        Destroy(a.image.gameObject); // Imageを破壊
        Destroy(a.gameObject); // 敵を破壊
        enemys.Remove(a); // 敵をリストから削除
    }

    public void InstantiateEnemy(Vector3 v, Quaternion q)
    {
        AgentScript3 s = Instantiate(enemy, v, q).GetComponent<AgentScript3>();
        s.sc_radar = this;
        enemys.Add(s);
    }

    public Vector3 GetRandomPoint()
    {
        return points[Random.Range(0, points.Length - 1)].position;
    }

}

ミニマップの画像と敵の色を合わせるためには、Imageオブジェクトがどの敵と対応するのかわからないといけないと思ったので、各敵につけるスクリプトに新しく作るImageオブジェクトを持たせておきます。

敵に伝える目的地として、地面に複数の空のゲームオブジェクトを配置しています。目的地をランダムに選ぶメソッドを各敵から呼ぶようにしたので、このスクリプトも各敵に教えます。

ミニマップ上の点を動かす処理は前の記事と同じですが、敵が複数いるのでfor文で繰り返しています。また、敵を新しく作ったときにImageオブジェクトも作ると、ミニマップ上の正しい位置にそれを配置するまでの間に、一瞬違う場所に白丸ができるのが見えてしまうので、for文の中で、敵がImageオブジェクトを持っているかを確かめて、持っていなければ作ります。

敵を作ったり消したりするときは、敵のリストからも追加・削除します。

敵の生成
敵の削除
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;

public class AgentScript3 : MonoBehaviour
{

    public RectTransform image;
    public RadarTest sc_radar;
    NavMeshAgent agent;
    MeshRenderer meshRenderer;

    List colors = new List() { Color.red, Color.yellow, Color.blue, Color.green};

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        meshRenderer = GetComponent<MeshRenderer>();      

    }

    // Update is called once per frame
    void Update()
    {
        
        if (!agent.pathPending && agent.remainingDistance < 0.5f)
        {
            agent.destination = sc_radar.GetRandomPoint(); // 次の目的地をランダムに設定

            Color c = colors[Random.Range(0, colors.Count - 1)]; // 色をランダムで決める
            if(image) image.GetComponent<Image>().color = c; // ミニマップ上の画像の色を変える
            meshRenderer.material.SetColor("_BaseColor", c); // 敵の色を変える
        }
        
    }
}

各敵のスクリプトでは、目的地に着いたら次の目的地をランダムに設定し、そのときにランダムに色を変えます。

コメントを残す

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