一定距離を保ち、プレイヤーを追尾しつつ、円運動する敵キャラのコード。
キャラ向きの補正あり。円運動の移動方向の反転処理も軽く書いています。
- この使用例では多分大丈夫だと思いますが、エラーが出る場合は、GameManagerの実行順を早めに設定してください。
- 上部メニュー -> Edit -> Project Settings…を選択。
- Project Settingsウィンドウ -> サイドメニュー -> Script Execution Orderを選択。
- 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
- 敵キャラのメインスクリプトへ追記するか、新規スクリプトを作成して貼り付け。
- 当たり判定を付ける場合は、地面レイヤーとの判定を無効化しておく。
- Enemyレイヤーを作成&敵キャラにレイヤーを設定。
- Groundレイヤーを作成&地面オブジェクトにレイヤーを設定。
- 上部メニュー -> Edit -> Project Settings…を選択。
- Project Settingsウィンドウ -> サイドメニュー -> Physics2Dを選択。
- 下までスクロール -> 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);
}
}