Unityチュートリアル:Raycastで特定のオブジェクトのみを検出する方法
このチュートリアルでは、Unityを使用してシーン上に複数のオブジェクト(敵、プレイヤー、障害物)を配置し、Physics.Raycast
を活用して特定のオブジェクト(プレイヤー)にのみヒットさせる方法を学びます。具体的には、Raycastが自身や他の敵オブジェクトにヒットしないようにし、障害物が存在する場合にはプレイヤーを検出しないように設定します。
1. プロジェクトのセットアップ
Unity Hubを開く:
- 最新のUnityバージョンをインストールしていない場合は、Unityの公式サイトからダウンロードしてください。
新しいプロジェクトの作成:
- Unity Hubで「新規プロジェクト」をクリックし、「3D」テンプレートを選択します。
- プロジェクト名を「RaycastTutorial」とし、保存場所を指定して「作成」をクリックします。
2. オブジェクトの配置
シーンに必要なオブジェクト(Enemy1, Enemy2, Player, Obstacle)を配置します。
Enemy1とEnemy2の作成:
Hierarchy
ウィンドウで右クリック →3D Object
→Sphere
を選択します。名前を「Enemy1」に変更します。- 同様にもう一つのSphereを作成し、「Enemy2」に変更します。
Playerの作成:
Hierarchy
ウィンドウで右クリック →3D Object
→Capsule
を選択します。名前を「Player」に変更します。
Obstacleの作成:
Hierarchy
ウィンドウで右クリック →3D Object
→Cube
を選択します。名前を「Obstacle」に変更します。
オブジェクトの配置:
Scene
ビューで各オブジェクトを一直線上に配置します。例えば、X軸を基準に以下のように配置します。 オブジェクト 位置 (X, Y, Z) Enemy1 (-4, 0, 0) Enemy2 (-2, 0, 0) Obstacle (0, 0, 0) Player (2, 0, 0)- 各オブジェクトの
Transform
コンポーネントで位置を設定します。
カメラの調整:
Main Camera
を選択し、Transform
の位置を(0, 5, -10)
に、回転を(30, 0, 0)
に設定して全体を見渡せるようにします。
3. レイヤーの設定
Raycastが特定のレイヤーのオブジェクトのみを検出するように、各オブジェクトにレイヤーを割り当てます。
新しいレイヤーの作成:
Inspector
ウィンドウで任意のオブジェクトを選択し、上部のLayer
ドロップダウンをクリック →Add Layer...
を選択します。- 以下のレイヤーを追加します:
Enemy
(例:レイヤー8)Player
(例:レイヤー9)Obstacle
(例:レイヤー10)
オブジェクトにレイヤーを割り当てる:
- 各オブジェクトを選択し、
Inspector
のLayer
ドロップダウンから対応するレイヤーを選択します。Enemy1
とEnemy2
→Enemy
Player
→Player
Obstacle
→Obstacle
レイヤーマスクの理解:
- レイヤーマスクを使用すると、Raycastが特定のレイヤーのオブジェクトのみを検出または無視するように設定できます。
4. Raycastの実装
Enemy1からPlayerに向かってRayを飛ばし、Enemy2や自身にヒットしないように設定します。また、Obstacleが間にある場合はPlayerを検出しないようにします。
スクリプトの作成:
Project
ウィンドウで右クリック →Create
→C# Script
を選択し、「EnemyRaycast」と命名します。Enemy1
オブジェクトにこのスクリプトをドラッグ&ドロップしてアタッチします。
スクリプトの編集:
using UnityEngine;
public class EnemyRaycast : MonoBehaviour
{
public Transform player; // プレイヤーのTransformを設定
public float maxDistance = 100f; // レイの最大距離
public LayerMask hitLayers; // レイがヒットするレイヤー
void Update()
{
// プレイヤーへの方向を計算
Vector3 direction = player.position - transform.position;
// レイキャストを実行
if (Physics.Raycast(transform.position, direction, out RaycastHit hit, maxDistance, hitLayers))
{
if (hit.collider.gameObject.CompareTag("Player"))
{
Debug.Log("Playerが検出されました!");
// ここにプレイヤーを検出した際の処理を追加
}
else
{
Debug.Log("Playerは検出されていません。");
}
}
else
{
Debug.Log("何もヒットしませんでした。");
}
// デバッグ用にレイを表示
Debug.DrawRay(transform.position, direction.normalized * maxDistance, Color.red);
}
}
プレイヤーの設定:
Player
オブジェクトにタグを設定します。Player
を選択し、Inspector
のTag
ドロップダウンからPlayer
を選択します(存在しない場合は新規作成)。
スクリプトの設定:
Enemy1
を選択し、Inspector
のEnemyRaycast
コンポーネントで以下を設定します:Player
フィールドにPlayer
オブジェクトをドラッグ&ドロップ。Hit Layers
フィールドでPlayer
レイヤーのみを選択します(レイヤーマスクを設定)。
Hit Layers
の隣にあるドロップダウンをクリックし、Player
レイヤーにチェックを入れます。これにより、RaycastはPlayerレイヤーのオブジェクトのみを検出します。
5. 障害物の影響を考慮する
Obstacleが間にある場合、Playerを検出しないようにRaycastの設定を追加します。
レイヤーマスクの拡張:
EnemyRaycast
スクリプトを修正して、Obstacleレイヤーも含めます。ただし、Playerのみを検出対象とします。
using UnityEngine;
public class EnemyRaycast : MonoBehaviour
{
public Transform player; // プレイヤーのTransformを設定
public float maxDistance = 100f; // レイの最大距離
public LayerMask hitLayers; // レイがヒットするレイヤー
void Update()
{
// プレイヤーへの方向を計算
Vector3 direction = player.position - transform.position;
// レイキャストを実行
if (Physics.Raycast(transform.position, direction, out RaycastHit hit, maxDistance, hitLayers))
{
if (hit.collider.gameObject.CompareTag("Player"))
{
Debug.Log("Playerが検出されました!");
// ここにプレイヤーを検出した際の処理を追加
}
else
{
Debug.Log("Playerは検出されていません。");
}
}
else
{
Debug.Log("何もヒットしませんでした。");
}
// デバッグ用にレイを表示
Debug.DrawRay(transform.position, direction.normalized * maxDistance, Color.red);
}
}
Obstacleの設定:
Obstacle
オブジェクトのLayer
をObstacle
に設定します。
レイヤーマスクの調整:
EnemyRaycast
コンポーネントのHit Layers
フィールドでPlayer
レイヤーのみを選択します。Obstacleレイヤーは選択しないことで、RaycastがObstacleにヒットした場合はPlayerに到達できなくなります。
スクリプトの改善(高度な方法):
- 複数のレイヤーを考慮してRaycastを行い、ObstacleがPlayerとEnemyの間にあるかどうかを判断します。
using UnityEngine;
public class EnemyRaycast : MonoBehaviour
{
public Transform player;
public float maxDistance = 100f;
public LayerMask obstacleLayers; // 障害物のレイヤー
void Update()
{
Vector3 direction = player.position - transform.position;
float distance = Vector3.Distance(transform.position, player.position);
// Obstacleを先にチェック
if (Physics.Raycast(transform.position, direction, out RaycastHit hitObstacle, distance, obstacleLayers))
{
Debug.Log("障害物がPlayerとEnemyの間にあります。");
return;
}
// Playerをチェック
if (Physics.Raycast(transform.position, direction, out RaycastHit hitPlayer, maxDistance, LayerMask.GetMask("Player")))
{
if (hitPlayer.collider.gameObject.CompareTag("Player"))
{
Debug.Log("Playerが検出されました!");
}
}
else
{
Debug.Log("Playerは検出されていません。");
}
// デバッグ用にレイを表示
Debug.DrawRay(transform.position, direction.normalized * maxDistance, Color.red);
}
}
- スクリプトの設定:
Obstacle Layers
フィールドにObstacle
レイヤーを選択します。- これにより、RaycastはまずObstacleにヒットするかを確認し、Obstacleがない場合にのみPlayerを検出します。
6. まとめ
このチュートリアルでは、以下のポイントを学びました:
- オブジェクトの配置: シーン内に複数のオブジェクトを配置し、位置を調整する方法。
- レイヤーの設定: オブジェクトにレイヤーを割り当て、Raycastの対象を制御する方法。
- Raycastの実装:
Physics.Raycast
を使用して特定のオブジェクト(Player)にのみヒットさせる方法。 - 障害物の考慮: 障害物が間にある場合にRaycastがPlayerを検出しないようにする方法。
ディスカッション
コメント一覧
まだ、コメントがありません