【Unity/2D】プレイヤーを中心に円運動する敵キャラを作成

プレイヤーを追尾しつつ、円運動する敵キャラ(床通過Ver)

一定距離を保ち、プレイヤーを追尾しつつ、円運動する敵キャラのコード。
キャラ向きの補正あり。円運動の移動方向の反転処理も軽く書いています。

  • この使用例では多分大丈夫だと思いますが、エラーが出る場合は、GameManagerの実行順を早めに設定してください。
    1. 上部メニュー -> Edit -> Project Settings…を選択。
    2. Project Settingsウィンドウ -> サイドメニュー -> Script Execution Orderを選択。
    3. GameManagerを基準より上側に設置。

サンプル動画

床貫通Ver

スーパーマリオシリーズのジュゲム的な感じですね。

床衝突で反転Ver

現在作っているシューティング風ゲームで使ったパターン。

前提

  • 基本的なPlayerを作成(画像、当たり判定、移動等)。
  • 基本的なEnemyを作成(画像、当たり判定等)。

【コード】Player

  • プレイヤーのメインスクリプトへ、tf変数の宣言&設定部分を追記する。
  • transformを頻繁に読み取るので、別で参照を保持しているだけです。


//使わなかったので、一応コメントアウト。
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{

//敵キャラがGameManagerを介して、プレイヤーの位置情報を読み取れるようにpublicにしている。
	public Transform tf;

	void Awake()
	{
		tf = transform;
	}

//移動やスプライトの更新部分は割愛。    



}

【コード】 Enemy

  • 敵キャラのメインスクリプトへ追記するか、新規スクリプトを作成して貼り付け。
  • 当たり判定を付ける場合は、地面レイヤーとの判定を無効化しておく。
    1. Enemyレイヤーを作成&敵キャラにレイヤーを設定。
    2. Groundレイヤーを作成&地面オブジェクトにレイヤーを設定。
    3. 上部メニュー -> Edit -> Project Settings…を選択。
    4. Project Settingsウィンドウ -> サイドメニュー -> Physics2Dを選択。
    5. 下までスクロール -> Layer Collision Matrixで、Enemy x Ground間の衝突判定を無効化。
  • Rigidbody 2Dを付けるなら、Gravity Scaleを0にしておく。


//使わなかったので、一応コメントアウト。
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{

//transformで毎フレーム取得すると負荷が掛かる為、別に参照を保持。
	Transform tf;

//左向き時のRotation。使用する画像素材によっては左右逆かも。
	Quaternion leftRotation = Quaternion.Euler(0, 180, 0);
//右向き時のRotation。
	Quaternion rightRotation = Quaternion.Euler(0, 0, 0);

//-1.0fで時計回り、1.0fで反時計回り。
	float direction = -1.0f;

//移動速度というか移動角度。
	float moveSpeed = 3.0f;

//プレイヤーを追尾する速度のレート(大きい程高速)。
	float followRate = 0.1f;

//追尾するポイントのプレイヤーからの距離(つまり小さい程、近付く)。
	float followTargetDistance = 5.0f;



	void Awake()
	{
		tf = transform;
	}

//衝突判定を取る場合に備え、移動をFixedUpdate内で実行している。
	void FixedUpdate()
	{
//一応nullチェックしている。
		if (GameManager.Instance.player != null) {

//プレイヤーを一定の距離で追尾。
			tf.position = Vector3.Lerp(tf.position, GameManager.Instance.player.tf.position + (tf.position - GameManager.Instance.player.tf.position).normalized * followTargetDistance, followRate);

//プレイヤーを中心に円運動。
			tf.RotateAround(GameManager.Instance.player.tf.position, Vector3.forward, direction * moveSpeed);

//敵キャラからプレイヤーへの横向きのベクトルが、マイナスならば左向きに、プラスならば右向きに設定。0ならば無視。
//RotateAroundで向きが変わるので、毎フレームRotationを上書きしている。
//Rotation自体を変えると不都合なら、SpriteRenderer.flipXを切り替えても良い。  
			if (GameManager.Instance.player.tf.position.x - tf.position.x < 0) {
				tf.rotation = leftRotation;
			} else if (0 < GameManager.Instance.player.tf.position.x - tf.position.x) {
				tf.rotation = rightRotation;
			}

		}
	}

//回転方向を反転。
	void Turn()
	{
		direction = -direction;
	}

//地面への侵入を制限する場合は、当たり判定を付けて、コレのコメントアウトを外す。
//地面オブジェクトに「Ground」タグを付けておく。
/*
	void OnCollisionEnter2D(Collision2D col)
	{

		if (col.gameObject.CompareTag("Ground")) {
			Turn();
		}
	}
*/

}

【コード】 GameManager

  • GameManagerへ追記するか、新規オブジェクトにスクリプトを作成して貼り付け。


//使わなかったので、一応コメントアウト。
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{

	public static GameManager Instance = null;

//インスペクターからプレイヤーを紐付けしておく。
	public Player player;



	void Awake()
	{
		if (Instance == null)
			Instance = this;
		else if (Instance != this)
			Destroy(gameObject);

		DontDestroyOnLoad(gameObject);


	}


}

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