【Unity】隠れた相手が現れたら見つける
3Dオブジェクト同士で、相手が隠れている状態では見つけられなくて、ひょこっと現れたら見つけてしまうようにしましょう
学習用のサンプル動画
シーン構成
相手を見つけようとしているオブジェクト
Cubeです
1つの見つける機能を持った後述するDetectTestスクリプト(コンポーネント)をアタッチしています
隠れる障害物
Cubeでスケールを増やしています
見つけたい相手
Capsuleで、Character Controllerをアタッチしています
CharacterController内蔵のコライダーを使うので、CapsuleコライダーはRomoveしておきます
コード
テスト用のサンプルコードになります
これは、スクリプトと呼ばれていますが、実体はクラスですね
データの部分は、次のフィールド一覧で
振る舞いの部分は、メソッド一覧を確認してみましょう
フィールド一覧
型 | フィールド名 | 意味 |
Vector3 | playerTran | チェック相手のTransform |
RaycastHit[] | raycastHits | Rayを飛ばしたチェック相手のコライダーにヒットした情報(複数の相手の情報を配列で保存) |
Vector3 | positionDiff | チェック相手との距離の差のベクトル(3次元空間) |
float | distance | チェック相手との距離(いわゆるメートル) |
Vector3 | direction | チェック相手の方向(方向情報だけなので大きさは1:正規化と言います) |
int | hitCount | 相手との間のコライダーの数(相手のコライダーも含む) |
メソッド一覧
Calcメソッド(計算)
positionDiff = playerTran.position - transform.position;
distance = positionDiff.magnitude;
direction = positionDiff.normalized;
hitCount = Physics.RaycastNonAlloc(transform.position, direction, raycastHits, distance);
DrawRayLineメソッド(デバッグ用のRayの描画)
チェックする相手にCharacterControllerコンポーネントがアタッチされています
これには、Colliderがアタッチされているのでコライダーカウントがされます(間違っている情報があるので気をつけましょう)
DrawRayメソッドは、シーンビューにRayを描画します
第1引数は、ラインを引く始点
第2引数は、方向のベクトル(長さも関係あり)
第3引数は、ライン色
hitCount が1の時、つまり、チェックしたい相手との間に障害物がないときは、緑で
障害物があるときは、赤で線を引きます
if (hitCount == 1)
{
Debug.DrawRay(transform.position, positionDiff, Color.green);
}
else
{
Debug.DrawRay(transform.position, positionDiff, Color.red);
}
OnGUIメソッド(Unityのイベントハンドラ)
ゲームビューにデバッグ情報を表示するために使います
DrawRayメソッドで、シーンビューに描画します
第1引数は、表示する四角形情報(Rect構造体は、四角形の始点(x)、四角形の始点(y)、幅、高さ)
第2引数は、表示文字列になります
Rect rect = new Rect(10, 10, 500, 20);
GUI.Label(rect, $"ヒットカウント: {hitCount}");
rect = new Rect(10, 30, 500, 20);
GUI.Label(rect, $"相手とのベクトル:{positionDiff}");
rect = new Rect(10, 50, 500, 20);
GUI.Label(rect, $"距離:{distance}");
rect = new Rect(10, 70, 500, 20);
GUI.Label(rect, $"方向:{direction}");
見つけたオブジェクトの名前をゲームビューに表示しています
for (int i = 0; i < hitCount; i++)
{
rect = new Rect(10, columnCount, 500, 20);
GUI.Label(rect, $"ヒットオブジェクト{i}:{raycastHits[i].transform.name}");
columnCount += 20;
}
全体
using UnityEngine;
using System;
public class DetectTest : MonoBehaviour
{
// チェック相手のTransform(欲しいのは、Position情報)
[SerializeField]
Transform playerTran;
// Rayを飛ばしたチェック相手のコライダーにヒットした情報を配列で取得するための変数
RaycastHit[] raycastHits = new RaycastHit[10];
// チェック相手との差をベクトルで管理
Vector3 positionDiff;
// チェック相手との距離
float distance;
// チェック相手の方向情報(大きさ情報を無しにしています:つまり大きさは1)
Vector3 direction;
// 相手オブジェクトとの間のコライダーの数(Pivot間)
int hitCount;
void Update()
{
Calc();
DrawRayLine();
}
private void Calc()
{
positionDiff = playerTran.position - transform.position;
distance = positionDiff.magnitude;
// distance = Vector3.Distance(playerTran.position, transform.position);
direction = positionDiff.normalized;
// direction = Vector3.Normalize(positionDiff);
hitCount = Physics.RaycastNonAlloc(transform.position, direction, raycastHits, distance);
}
private void DrawRayLine()
{
if (hitCount == 1)
{
Debug.DrawRay(transform.position, positionDiff, Color.green);
}
else
{
Debug.DrawRay(transform.position, positionDiff, Color.red);
}
}
void OnGUI()
{
Rect rect = new Rect(10, 10, 500, 20);
GUI.Label(rect, $"ヒットカウント: {hitCount}");
rect = new Rect(10, 30, 500, 20);
GUI.Label(rect, $"相手とのベクトル:{positionDiff}");
rect = new Rect(10, 50, 500, 20);
GUI.Label(rect, $"距離:{distance}");
rect = new Rect(10, 70, 500, 20);
GUI.Label(rect, $"方向:{direction}");
int rowCount = 90;
for (int i = 0; i < hitCount; i++)
{
rect = new Rect(10, rowCount, 500, 20);
GUI.Label(rect, $"ヒットオブジェクト{i}:{raycastHits[i].transform.name}");
rowCount += 20;
}
}
}
ディスカッション
コメント一覧
まだ、コメントがありません