Trigger
Trigger はゴースト化した Collider です——進入・滞在・退出を検知しても押し返しません。チェックポイント、ピックアップ、自動ドア、ダメージゾーンに使い、Rigidbody 条件と OnTriggerEnter の基礎を学べます。図解とシミュレーターでゾーン反応を体感し、自学にも使えます。
想像してみてください...
Trigger はスーパーの自動ドアのセンサーのようなものです。入っても押し返さず、 気づいてドアを開けるだけ。物理的な力はなく、「誰かが入った」という信号だけ。 Unity では `OnTriggerEnter` がその信号——ゾーンに触れた瞬間に発火し、ドアを開ける、回復する、カットシーンを始める…などに使えます。
概念の詳細
Trigger は通常の Collider で Is Trigger にチェックを入れたものです。有効にすると
すり抜け可能になり——押し返しはありません。代わりに Unity は三つのコールバックを発火します:
OnTriggerEnter(進入時)、OnTriggerStay
(内側にいる毎フレーム)、OnTriggerExit(退出時)。
Trigger が発火するには、二者のうち少なくとも一方に
Rigidbody が必要です。これが典型的な取りこぼし——両方静的(Rigidbody なし)だと
互いにトリガーしません。重力が不要なら isKinematic = true にします。
Trigger の用途は広い:checkpoint(通過で位置保存)、 pickup zone(アイテム取得)、 enemy detection(AI の感知半径)、 damage zone(火・酸)、 cutscene trigger(ストーリー開始)。本物の物理は不要—— 「誰がこの体積に入ったか」だけです。
Unity 2D では対応コールバックが OnTriggerEnter2D、
OnTriggerStay2D、OnTriggerExit2D — 形は同じですが引数は
Collider ではなく Collider2D です。
Trigger と Collision のライフサイクル
Trigger (isTrigger = true)
OnTriggerEnter
接触した最初のフレーム
OnTriggerStay
内部にいる間の毎フレーム
OnTriggerExit
離脱する最後のフレーム
✅ 通り抜け可能 — 反力なし
Collision (isTrigger = false)
OnCollisionEnter
衝突した最初のフレーム
OnCollisionStay
接触中の毎フレーム
OnCollisionExit
離れたとき
🔒 ブロックされる — 物理的な反力あり
⚠️ 必須条件:
2 つのオブジェクトのうち少なくとも一方に Rigidbody(または Rigidbody2D)がないと、trigger/collision は発火しません。
ハンズオン手順
トリガー体積を作成
空の GameObject を作り、Add Component → BoxCollider、"Is Trigger" にチェック。ゾーンの大きさに合わせます。
動く側に Rigidbody を付ける
キャラや弾には Rigidbody が必要。重力をかけたくなければ isKinematic = true。
トリガーハンドラを書く
トリガー側または動く側に OnTriggerEnter(Collider other) を持つスクリプトを追加します。
Layer でフィルタ
other.gameObject.layer や CompareTag で、関心のある物体だけに反応します。
Gizmo の色でデバッグ
Trigger はシアン(通常の衝突は緑)。追加のデバッグ描画には OnDrawGizmos を使います。
インタラクティブシミュレーター
← → キー(または下のボタン)でキャラを動かし、トリガーゾーンを通過してみましょう。
キャラクターをトリガー領域へ移動...
コード例
基本シンプルなピックアップ:プレイヤーがトリガーに入るとコインを取得。
using UnityEngine;
// Attach this to a Coin with a Collider that has isTrigger = true
public class CoinPickup : MonoBehaviour
{
public int value = 10;
public AudioClip pickupSound;
void OnTriggerEnter(Collider other)
{
// Only react to the Player
if (!other.CompareTag("Player")) return;
// Award points via GameManager
GameManager.instance.AddScore(value);
// Play a pickup sound
AudioSource.PlayClipAtPoint(pickupSound, transform.position);
// Remove the coin from the scene
Destroy(gameObject);
}
}コード例
上級時限ハザード:内側にいる間は毎フレームダメージ、退出で停止。
using UnityEngine;
using System.Collections;
// A fire zone that damages while you stand in the trigger
public class DamageZone : MonoBehaviour
{
public float damagePerSecond = 10f;
public LayerMask damageable;
Coroutine damageRoutine;
PlayerHealth currentTarget;
void OnTriggerEnter(Collider other)
{
if ((damageable.value & (1 << other.gameObject.layer)) == 0) return;
currentTarget = other.GetComponent<PlayerHealth>();
if (currentTarget != null)
damageRoutine = StartCoroutine(DamageLoop());
}
void OnTriggerExit(Collider other)
{
if (damageRoutine != null)
{
StopCoroutine(damageRoutine);
damageRoutine = null;
currentTarget = null;
}
}
IEnumerator DamageLoop()
{
while (true)
{
currentTarget.TakeDamage(damagePerSecond * Time.deltaTime);
yield return null; // Wait one frame
}
}
}📌 要点
- ▸isTrigger=true → すり抜け、イベント受信
- ▸少なくとも一方に Rigidbody が必要
- ▸CompareTag() は文字列直接比較より速い
- ▸OnTriggerStay は毎フレーム——コストに注意
- ▸LayerMask で安くフィルタ
⚠️ よくあるミス
❌ isTrigger がオンなのに Trigger が発火しない
どちらにも Rigidbody がない
✅ 動く側に Rigidbody を追加(必要なら isKinematic=true)
❌ OnTriggerStay 内で Destroy(other.gameObject)
物理ループの途中で破棄されエラー
✅ OnTriggerEnter で Destroyし、先に null チェック