【Unity】スライムが複数いると追跡をやめる原因と対処法|Raycastとレイヤー設定を理解しよう
- 1. こんな現象に心当たりはありませんか?
- 2. まず調べてみよう:Visual Studioのブレークポイントで原因を突き止める
- 3. ポイント1 原因は「視線チェックのRaycastが、他のスライムの索敵エリアに当たっている」
- 4. ポイント2 なぜ「複数体のときだけ」起きるのか
- 5. ポイント3 対処:索敵エリア専用のレイヤーを作る
- 6. ポイント4 コードでさらに安全にする:QueryTriggerInteraction.Ignore
- 7. ポイント5 とりあえず直したいときは Enemy レイヤーでもOK
- 8. よくある勘違い:Physics Materialやマトリクスのせい?
- 9. 動作確認のポイント
- 10. まとめ
- 11. 関連記事
こんな現象に心当たりはありませんか?
Unityでアクションゲームを作っているとき、敵のスライムを複数体置いたところ、次のような動きになりませんでしたか。
- スライムがプレイヤー(クエリちゃん)を追いかけている途中で、急に立ち止まる
- スライムが1体だけのときは、ちゃんと追いかけてくる
- 他のスライム(味方)が近くにいるときに限って、追跡が止まる
スクリプトにミスは見当たらないのに、複数体にしたとたんに起きる――このようなバグは、実はスクリプトではなく、レイヤーの設定が原因です。この記事では、原因をたどり、初学者の方でも理解して直せるように解説します。
取り上げるのは、敵がプレイヤーを索敵して追いかける、次のような構成です。
- 索敵エリア:スライムの子オブジェクト
CollisionDetector(半径4のトリガーSphere Collider) - 追跡処理:
EnemyMove.OnDetectObject(索敵エリアに入った相手が Player タグなら、NavMeshAgentで追いかける)
まず調べてみよう:Visual Studioのブレークポイントで原因を突き止める
スクリプトにミスが見当たらないのに動きがおかしいとき、設定を手当たり次第に変えるのは遠回りです。今回のバグは、構文エラーでも例外でもなく、プログラムは指示どおり動いているのに、想定していた条件と実際の条件が違っているタイプです。このタイプは、Visual Studioのブレークポイントでコードを途中で止め、実際の値を見る方法が最短の調べ方です。
調べたいこと
追跡を止めているのは、次の分岐です(コード全体は、このあとの「ポイント1」に載せています)。
if (hitCount == 0)
{
// 間に何もない → 追いかける
}
else
{
// 何かに当たった → 停止する
}
ここで確かめたいことは3つです。
hitCountは、本当に 0 以外になっているのか- Raycast は、何に当たっているのか
- なぜ、障害物ではないものに当たるのか
ブレークポイントを置いて止める
- Visual Studio で
elseの中の_agent.isStopped = true;の行の左余白をクリックし、赤い丸(ブレークポイント)を置く - スライムを2体以上近くに置く(再生の前に行う)
- Visual Studio の「Unityにアタッチ」を押し、Unity で再生する
- プレイヤーを索敵範囲に入れる。追跡が止まる症状が出た瞬間に、ブレークポイントの行で実行が止まる
if (hitCount == 0) の行は、追跡が正常に動いている間も毎フレーム通ります。そこに置くと、症状が出る前から止まってしまい、見えるのはプレイヤーに当たった結果だけです。追跡が止まる側の else に置けば、「視線が遮られた」と判断された瞬間だけを捕まえられます。

else の中の _agent.isStopped = true; の行(黄色)でプログラムが停止した状態アタッチや Debug Mode の切り替えがはじめての方は、先に Unity×Visual Studio 連携でC#デバッグを始めよう をご覧ください。
停止したら値を見る
停止中は、変数にマウスを重ねるか、Watchウィンドウに式を入力すると値を確認できます。見る場所と、原因に近づく値の例は次のとおりです。
| 調べること | 見る式(Watchウィンドウ) | 原因に近づく値の例 |
|---|---|---|
| hitCount の値 | hitCount | 1(0ではない) |
| 当たった相手の名前 | _raycastHits[0].collider.name | CollisionDetector |
| トリガーかどうか | _raycastHits[0].collider.isTrigger | true |
| 当たった相手のレイヤー | LayerMask.LayerToName(_raycastHits[0].collider.gameObject.layer) | Default |
| レイの対象レイヤー | raycastLayerMask.value | 1(Defaultレイヤーのみ) |
実際にこのプロジェクトで停止し、自動ウィンドウで _raycastHits[0] を開くと、次のように表示されます。
![停止中の自動ウィンドウ。hitCount は 2、_raycastHits[0] の collider は CollisionDetector の Sphere Collider と表示されている](https://soft-rime.com/wp-content/uploads/2026/10/slime-debug-auto-hit.jpg)
hitCount は 2、_raycastHits[0] の collider は CollisionDetector と表示されている_raycastHits[0] が有効なのは、hitCount が 1 以上のときだけです。また、RaycastNonAlloc が返す配列は、距離順に並ぶとは限りません。hitCount が 2 以上のときは、0番目だけでなく、hitCount 個ぶんの要素をすべて確認すると確実です。
当たった相手の持ち主を見る(parent)
CollisionDetector は、スライムの子オブジェクトです。そのため、_raycastHits[0] の collider の transform を開いて parent を見ると、当たった索敵エリアがどのスライムのものかがわかります。Watchウィンドウに _raycastHits[0].collider.transform.parent.name と入力しても確認できます。

collider の transform を開いた自動ウィンドウ。parent は Slime_Green と表示されている止まっているスライム(this)は Slime_Green(Clone) ですが、当たった CollisionDetector の parent は Slime_Green です(root も同じ Slime_Green です)。名前が異なるので、視線を遮ったのは、止まっているスライム自身ではなく、別のスライムの索敵エリアだとわかります。
値からわかること
hitCount が 1 で、当たった相手が CollisionDetector(トリガー、Defaultレイヤー)であれば、レイが当たっているのは壁や地形ではなく、他のスライムの索敵エリアだとわかります。レイの対象レイヤーも Default なので、索敵エリアが視線チェックの対象に入っている、というのが原因です。次の「ポイント1」からは、この仕組みを順に説明し、直し方へ進みます。
調査の流れ
- 現象を再現する:スライム1体なら正常、複数体なら追跡が止まる
- ブレークポイントで調べる:
hitCountと、当たった Collider を確認する - 原因を特定する:他のスライムの索敵エリアに、レイが当たっている
- 直して、もう一度確かめる:ポイント3・ポイント4の対処のあと、同じ場所で止めて
hitCountが 0 になることを確認する
設定を変えて「たまたま直った」で終わらせず、値で原因を確かめる習慣をつけておくと、次に別のバグが起きたときにも、同じ調べ方を応用できます。
ポイント1 原因は「視線チェックのRaycastが、他のスライムの索敵エリアに当たっている」
スライムは、プレイヤーを見つけると、間に障害物がないかを Physics.RaycastNonAlloc で確かめてから追いかけます。問題の箇所は次のコードです。
var hitCount = Physics.RaycastNonAlloc(
transform.position, direction, _raycastHits, distance, raycastLayerMask);
if (hitCount == 0)
{
// 間に何もない → 追いかける
_agent.isStopped = false;
_agent.destination = collider.transform.position;
}
else
{
// 何かに当たった → 見失ったとみなして停止
_agent.isStopped = true;
}
このコードは「レイが1つでも何かに当たれば、障害物ありと判断する」作りです。ポイントは、何に当たるかを決めるのが raycastLayerMask である点です。
このプロジェクトでは、マスクは Default レイヤーのみになっていました。一方で、索敵エリアを担当する子オブジェクト CollisionDetector も Default レイヤーのままでした。
さらに、Raycastはトリガー(Is Trigger が ON の Collider)にも当たるという初期設定です(Physics.queriesHitTriggers がデフォルトで ON)。つまり、レイが他のスライムの索敵球を横切ると、「間に障害物がある」と判定されてしまいます。
ポイント2 なぜ「複数体のときだけ」起きるのか
流れを順に追うと、理由が見えてきます。
- スライムAがプレイヤーを見つけ、プレイヤーに向けてレイを飛ばす
- そのレイが、近くにいるスライムBの索敵球(半径4・Defaultレイヤー・トリガー)を横切る
- マスクに Default が含まれ、トリガーも無視されないので、レイが当たる
hitCountが 0 でなくなり、「見失った」扱いでスライムAが停止する
なお、スライムA自身の索敵球には当たりません。レイの始点が索敵球の内側にあるためです。そのためスライムが1体だけのときは問題が表に出ず、複数体置いて初めて症状が見えるのです。スライム同士が近づくほど、起きやすくなります。

ポイント3 対処:索敵エリア専用のレイヤーを作る
解決策は、索敵エリアを「レイが当たらないレイヤー」に移すことです。スクリプトは変えず、エディタの設定だけで直ります。索敵エリア専用のレイヤーを作る方法を、手順で紹介します。
手順A レイヤーを追加する
- メニューから Edit > Project Settings > Tags and Layers を開く
- Layers を開き、空いているスロットに
EnemyMoveTargetDetectorと入力する

手順B 索敵エリアにレイヤーを割り当てる
- スライムのプレハブを開く
- 子オブジェクト
CollisionDetectorを選択し、Inspector上部の Layer をEnemyMoveTargetDetectorに変更する - このモデルをバリアントやコピーで増やしている場合(大きいスライム、小さいスライムなど)は、それらも同じ設定になっているか確認する

CollisionDetector は、スライム本体(Slime_Green)の子オブジェクトです。Hierarchy ではスライム本体の下に入っています。Layer を変更するのは、この子オブジェクトだけです。
親のスライム本体の Layer を変えると、「子オブジェクトも変更しますか?」という確認が表示されます。ここで「はい」を選ぶと、スライム本体まで EnemyMoveTargetDetector になってしまうため、親の Layer は変更しないようにしましょう。
キャプチャーの Position が X0 Y0 Z0 になっているのは、親(スライム本体)の位置を基準にした相対位置(ローカル座標)だからです。子オブジェクトなので、スライムが動くと索敵エリアも一緒に動きます。また、On Trigger Stay には、親にある EnemyMove.OnDetectObject が登録されています。
手順C Layer Collision Matrix を整える
専用レイヤーを作ったら、Edit > Project Settings > Physics の Layer Collision Matrix で、どのレイヤーと当たり判定をするかを決めます。
EnemyMoveTargetDetectorの行・列を、Player とだけ ON にする- このレイヤーと他のレイヤーの組み合わせは、すべて OFF にする
マトリクスは「どのレイヤー同士で当たり判定を行うか」の一覧表です。センサー(索敵エリア)は、探したい相手の Player とだけ当たればよい、と役割から考えると理解しやすくなります。このプロジェクトでは、攻撃判定も同じ考え方です。
| レイヤー | 役割 | ON にする相手 |
|---|---|---|
EnemyMoveTargetDetector | 敵の索敵センサー | Player のみ |
EnemyAttack | 敵の攻撃判定 | Player のみ |
PlayerAttack | プレイヤーの攻撃判定 | Enemy のみ |

これで直る理由
Raycast Layer Maskは Default のままで、索敵エリアはマスクの対象外になるため、レイが当たらなくなる- 地形や壁など実体のある障害物(Defaultレイヤー)は、これまでどおり視線を遮る
- 索敵エリアは Player とだけ当たるので、プレイヤーを見つける動作はそのまま動く
ポイント4 コードでさらに安全にする:QueryTriggerInteraction.Ignore
レイヤー設定で直る方法は、「索敵エリアのレイヤーが、マスクに含まれていないこと」を前提にしています。この前提はコードのどこにも書かれていないため、後からレイヤーを変更したときに同じバグが再発する可能性があります。
そこで、Raycastの最後の引数に QueryTriggerInteraction.Ignore を渡して「視線チェックではトリガーを無視する」と宣言しましょう。
// 視線チェックでは索敵エリアなどのトリガーを無視し、実体のある障害物だけを対象にする
var hitCount = Physics.RaycastNonAlloc(
transform.position, direction, _raycastHits, distance,
raycastLayerMask, QueryTriggerInteraction.Ignore);
引数は、順に「始点、方向、結果を入れる配列、距離、レイヤーマスク、トリガーの扱い」です。
| 値 | 動き |
|---|---|
Ignore | トリガーを無視する(今回はこれ) |
Collide | トリガーにも当たる |
UseGlobal | 省略時の既定値。プロジェクト設定の Queries Hit Triggers に従う(デフォルトで ON) |
これで「レイヤー設定」と「コード」の二重の守りになり、レイヤー設定を変更しても追跡が止まりにくい構造になります。地形や壁など、トリガーではない Collider は、これまでどおり視線を遮ります。
ポイント5 とりあえず直したいときは Enemy レイヤーでもOK
新しいレイヤーを作るのがやや大がかりに感じる場合は、CollisionDetector の Layer を、スライム本体と同じ Enemy にするだけでも直ります。
- 新しいレイヤーも、Layer Collision Matrix の追加設定もいらない
- Enemy と Player の組み合わせは ON なので、プレイヤーを見つける動作もこれまでどおり
- Raycastのマスクは Default のままで、索敵エリアがマスクの対象外になる
索敵エリアはセンサーですので、役割で分けた専用レイヤー(ポイント3)のほうが、設計としてはすっきりします。まずは Enemy で動かして理解し、慣れたら専用レイヤーに進む、という順序もおすすめです。
よくある勘違い:Physics Materialやマトリクスのせい?
原因を探すときに疑いやすい、次の2点は今回のバグとは関係ありません。
- Physics Material:摩擦や反発を決める設定です。トリガー判定やレイキャストには影響しません
- Layer Collision Matrix:Collider同士の衝突とトリガーの発生だけを決めます。Raycastはマトリクスを見ず、コードで渡すレイヤーマスクだけで当たる相手を決めます
「衝突の設定」と「レイの設定」は別物と覚えておくと、トラブルシュートが速くなります。
動作確認のポイント
- シーンにスライムを、3体以上近くに置く
- プレイヤーをスライムの索敵範囲に入れ、追いかけてくることを確認する
- 他のスライムが間に入っても、追跡が止まらないことを確認する
- 壁や箱(Defaultレイヤーのコライダー)の裏に隠れたときは、これまでどおり追跡が止まることも確認する
- 他のスライムが間に入った状態でブレークポイントで止め、
hitCountが 0 になっていることを確認する
まとめ
- 現象:スライムを複数体置くと、追跡中に立ち止まる
- 原因:視線チェックのRaycastが、他のスライムの索敵エリア(Defaultレイヤー・トリガー)に当たっていた
- 調べ方:ブレークポイントで止めて
hitCountと当たった Collider を確認すると、原因を絞り込める - 対処:索敵エリアを専用レイヤーに分け、マトリクスで Player とだけ ON にする(簡易版は Enemy レイヤー)
- さらに安全に:
QueryTriggerInteraction.Ignoreで、視線チェックからトリガーを外す
レイヤーは「誰と誰が当たるか」を整理する道具です。スライムを増やすときは、最初から索敵エリアに専用レイヤーを割り当てる習慣をつけておくと、同じトラブルを防げます。
関連記事
- Unityで敵をプレイヤーの周りにランダム出現させる|NavMesh対応のSpawnerをコルーチンで作ろう
- Unityゲームにおける状態管理とキャラクター制御スクリプトの解説(敵の攻撃からプレイヤーの攻撃まで)
- Unity×Visual Studio 連携でC#デバッグを始めよう










ディスカッション
コメント一覧
まだ、コメントがありません