一直線でプレイヤーに向かってくる敵の作り方を簡単にご紹介[Unity]

Unity

どんなモノを作ろうとしているのか?

どういうことをしようとしているのか?
動画でお見せすると以下のような感じです。

敵のゲームオブジェクトがプレイヤーのゲームオブジェクトに
どんどん近づいてくるようなイメージですね。

これをどうやって実装するかサンプルのコードも記載しながら簡単にまとめたいと思います。

まずはザックリなにをするのか全体像を記載していきましょう。

1.敵ゲームオブジェクトとプレイヤーゲームオブジェクトを作成します
2.C#Script内で敵、プレイヤーそれぞれの位置情報を取得します(Start関数)
3.C#ScriptのUpdate関数内でフレーム毎に敵の位置情報を少しずつプレイヤーに近付けていきます。(Update関数)

ではそれぞれ詳細をみていきます。

1.敵ゲームオブジェクトとプレイヤーゲームオブジェクトを作成する

こちらは簡単ですね。単純にゲームオブジェクトを2つ作成します。
重要なのはそれぞれの位置情報です。
プレイヤーと敵のゲームオブジェクトは離しておきましょう。

例えば今回は
プレイヤーの位置(Transform.position)は(x,y,z) = (-2,-4,0)
敵の位置 (Transform.position)は(x,y,z) = (2,4,0)
としました。

2.C#Script内で敵、プレイヤーそれぞれの位置情報を取得します

ここでは結構色々することがあるので
最初にやることをまとめておきます。

1.C#Scriptの作成
2.C#Scriptを敵ゲームオブジェクトにアタッチする
3.C#Script内でプレイヤーのゲームオブジェクトを見つける
4.C#Script内で敵、プレイヤーそれぞれの位置情報をVector3型の変数に格納する

3.,4.あたりが訳わかめで分かりにくいかと思いますが
初心者でも分かるように説明いたしますので安心してください。
順を追ってみていきましょう!

1.C#Scriptの作成
まずは敵のゲームオブジェクトにアタッチするC#Scriptを作りましょう。
プロジェクトウィンドウ上で右クリック→Create→C#Scriptを選択します。

このC#Scriptの名前は「MoveToPlayer」としておきましょうか。

2.C#Scriptを敵ゲームオブジェクトにアタッチする
敵ゲームオブジェクトにMoveToPlayerをアタッチします。

3.C#Script内でプレイヤーのゲームオブジェクトを見つける
ここからC#Script内でのお話しになります。
まずは必要な変数を定義しましょう。
といっても変数はそんなに多くありません。

必要な変数は以下3つにします。
・敵の位置情報(Vector3)
・プレイヤーのゲームオブジェクト(GameObject)
・プレイヤーの位置情報(Vector3)

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

public class MoveToPlayer : MonoBehaviour
{
// ####################追記部分(開始)#####################
    private GameObject playerObject; // プレイヤーオブジェクト
    private Vector3 PlayerPosition; // プレイヤーの位置情報
    private Vector3 EnemyPosition; // 敵の位置情報
// ####################追記部分(終了)#####################

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

ここまで出来たらプレイヤーのゲームオブジェクトを見つけましょう。
ゲームオブジェクトを見つける方法は大きく分けて2つあります。
GameObject.Find(“ゲームオブジェクト名”)
GameObject.FindWithTag(“ゲームオブジェクトのタグ名”)

GameObject.Find(“ゲームオブジェクト名”)は全てのActiveなゲームオブジェクトが検索の対象になるので重くなりがちだそうです。
Activeというのは有効という意味で、一言でいうとSceneビュー上で見えているオブジェクトたちのことです。

GameObject.FindWithTag(“ゲームオブジェクトのタグ名”)は
上記と比較すると処理的に軽いそうです。

あまり処理が重くなるのはよろしくないので軽い方を採用しましょう。
まずタグを追加する必要があります。
タグの追加はInspectorウィンドウのTag→Add Tagから出来ます。
(今回は既にPlayerというタグが標準で登録されているのでそちらを使います)

タグの追加はAdd Tagから出来ます
Playerのタグを「Player」に設定しました

タグが追加できたらC#Scriptに戻ります。

プレイヤーの検索はゲームスタート時に一度取得すればよいので
Start関数内に記述します。

GameObject player = GameObject.FindWithTag(“ゲームオブジェクトのタグ名”)

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

public class MoveToPlayer : MonoBehaviour
{
    private GameObject playerObject;
    private Vector3 PlayerPosition;
    private Vector3 EnemyPosition;

    // Start is called before the first frame update
    void Start()
    {
// ####################追記部分(開始)#####################
        playerObject = GameObject.FindWithTag("Player");
// ####################追記部分(終了)#####################
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

4.C#Script内で敵、プレイヤーそれぞれの位置情報をVector3型の変数に格納する

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

public class MoveToPlayer : MonoBehaviour
{
    private GameObject playerObject;
    private Vector3 PlayerPosition;
    private Vector3 EnemyPosition;

    // Start is called before the first frame update
    void Start()
    {
        playerObject = GameObject.FindWithTag("Player");

// ####################追記部分(開始)#####################
        PlayerPosition = playerObject.transform.position;
        EnemyPosition = transform.position;
// ####################追記部分(終了)#####################
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

EnemyPosition = transform.position
のtransform.positionで最初にゲームオブジェクトを省略しています。
この場合は、このC#Script(今回はMoveToPlayer.cs)がアタッチされているゲームオブジェクトの位置情報を取得するのでアタッチされているEnemyゲームオブジェクトの位置情報がEnemyPositionに格納されます。


ここまででやっと前提の作業が終わりました。
次が本題です。

3.C#ScriptのUpdate関数内でフレーム毎に敵の位置情報を少しずつプレイヤーに近付けていきます。(Update関数)

処理の流れ的には

プレイヤーと敵の位置情報を取得する

プレイヤーと敵の距離を計算し、距離を少し近付ける位置に敵を移動させる

分かりやすくするためにX座標のみで考えてみましょう

まずプレイヤーは-2の位置にいます。
敵は2の位置にいます。
距離はお互いの位置の差の絶対値なので
|-2 – 2| = 4と求まります。

次に敵の位置をお互いの距離が少し縮まる方向に移動させます。
例えば距離が1縮む方向に進めるとしましょう。

つまり敵の位置を2から1に変更すればよいですね。

これをUpdate関数内でどう表現するか?が肝ですね。

一番シンプルなのは以下のようなif文で分岐する感じでしょうか。

プレイヤーのx座標 > 敵のx座標 の場合
敵のx座標 = 敵のx座標 + 1
プレイヤーのx座標 < 敵のx座標 の場合
敵のx座標 = 敵のx座標 – 1

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

public class MoveToPlayer : MonoBehaviour
{
    private GameObject playerObject;
    private Vector3 PlayerPosition;
    private Vector3 EnemyPosition;

    // Start is called before the first frame update
    void Start()
    {
        playerObject = GameObject.FindWithTag("Player");

        PlayerPosition = playerObject.transform.position;
        EnemyPosition = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
// ####################追記部分(開始)#####################
        PlayerPosition = playerObject.transform.position;
        EnemyPosition = transform.position;

        if (PlayerPosition.x > EnemyPosition.x)
        {
            EnemyPosition.x = EnemyPosition.x + 0.01f;
        }
        else if (PlayerPosition.x < EnemyPosition.x)
        {
            EnemyPosition.x = EnemyPosition.x - 0.01f;
        }

        if (PlayerPosition.y > EnemyPosition.y)
        {
            EnemyPosition.y = EnemyPosition.y + 0.01f;
        }
        else if (PlayerPosition.y < EnemyPosition.y)
        {
            EnemyPosition.y = EnemyPosition.y - 0.01f;
        }

        transform.position = EnemyPosition;
// ####################追記部分(終了)#####################
    }
}

今回 1を加算(減算)すると大きすぎるので0.01を加算(減算)するようにしました。
ちゃんと考えればもっと綺麗にコーディングできるかと思いますが、こちらの方が分かりやすいかと思うのでif else ifで分岐させています。

これを実行すると冒頭の動画のようになります。


もう一つ考えられるのは距離の割合分を敵の位置に足してあげる方法です。
ちょっとイメージしづらい気がしているので具体的にみていきましょう。
今回お互いの距離は -2 – 2 = -4になります。
本来絶対値にしますがそうしないのがポイントですね。

例えばこちらの距離に対して10%敵を近づけるとしましょう。
つまり
敵の位置 += -4 * 0.1

こうすると敵の位置は
2 – 0.4 = 1.6となり、少しプレイヤーに近づいた位置に移動します。

コーディングすると以下のようになります。

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

public class MoveToPlayer : MonoBehaviour
{
    private GameObject playerObject;
    private Vector3 PlayerPosition;
    private Vector3 EnemyPosition;

    // Start is called before the first frame update
    void Start()
    {
        playerObject = GameObject.FindWithTag("Player");

        PlayerPosition = playerObject.transform.position;
        EnemyPosition = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
// ####################追記部分(開始)#####################
        PlayerPosition = playerObject.transform.position;
        EnemyPosition = transform.position;

        EnemyPosition.x += (PlayerPosition.x - EnemyPosition.x) * 0.01f;
        EnemyPosition.y += (PlayerPosition.y - EnemyPosition.y) * 0.01f;
        transform.position = EnemyPosition;
// ####################追記部分(終了)#####################
    }
}

これを実行してみると以下のようになります。

動画で見ると分かりやすいですが、相対距離の割合を加算していくため
最初は速く近づいていきますが段々ゆっくりになっていきます。

終わりに

どうでしたでしょうか?
今回は2パターンの近付き方を紹介したのですが、考えればもっといい方法がありそうですよね!(簡単には思いつきませんが…)

タイトルとURLをコピーしました