はじめてのイベントプログラミング:完全チュートリアル

ゲーム開発やアプリケーション制作を始めたばかりの皆さん、プログラミングを進めていく中で「イベント」という言葉を聞いたことがあるでしょうか?イベントは、ユーザーの操作やゲーム内の出来事に応じて特定の処理を実行するための重要な仕組みです。

本チュートリアルでは、初学者の方でも理解しやすいように、イベントの基本から活用方法までを丁寧に解説します。特に、コリジョンやトリガーを使った独自イベントの作り方についても実際にコードを書きながら学んでいきますので、ぜひ一緒に手を動かしてみてください。

イベントってなに?

イベントとは、ゲームやアプリで「何かが起こったときに、そのタイミングで特定の処理を実行する仕組み」のことです。

たとえば…

  • ボタンが押されたとき
  • キーボードのキーが押されたとき
  • 敵とぶつかったとき
  • タイマーで時間がきたとき

これらの「きっかけ」に応じて、自動的にプログラムが動いてくれます。


イベントを使わないとどうなるの?

最初はイベントを使わずにプログラムを書いても問題ないかもしれません。でも、機能をどんどん追加していくと、コードがごちゃごちゃになって大変になります。

例:スペースキーが押されたらライフを減らす

using UnityEngine;

public class Player : MonoBehaviour
{
    int life = 3;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            life--;
            Debug.Log("ライフが減った。残りライフ:" + life);
        }
    }
}

既存のプロジェクトで同じクラス名が存在する場合のクラス名の競合を避けるために、名前空間(Namespace)を活用する方法を紹介します。今回は、名前空間名を「イベントのテスト」のイメージであるEventTestNamespaceとします。以降のコードは全てこの名前空間に記述します

using UnityEngine;

namespace EventTestNamespace
{
    public class Player : MonoBehaviour
    {
        int life = 3;

        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                life--;
                Debug.Log("ライフが減った。残りライフ:" + life);
            }
        }
    }
}

これで十分と思うかもしれませんが、機能を追加していくと…

機能追加の例

  • ライフが0になったらゲームオーバーにする
  • プレイヤーを消す
  • 爆発アニメーションを再生する
  • スコアを更新する
  • 背景を点滅させる

これらを全部一つのUpdateメソッドに書いていくと、コードがどんどん長くなってしまいます。


イベントを使ってみよう!

イベントを使うと、コードをきれいに整理できて、新しい機能を追加するのも簡単になります。

3.1 基本的なイベントの作り方

Unityでは、UnityEventというクラスを使ってイベントを作成できます。

ステップ1:イベントを作るスクリプトを作成

  1. 新しいC#スクリプトを作成し、名前をEventTriggerとします。
  2. スクリプトを開き、以下のコードを書きます。
   using UnityEngine;
   using UnityEngine.Events;

   public class EventTrigger : MonoBehaviour
   {
       // UnityEvent型のイベントを宣言
       public UnityEvent myEvent;

       void Update()
       {
           if (Input.GetKeyDown(KeyCode.Space))
           {
               // イベントを発生させる
               myEvent.Invoke();
           }
       }
   }
  1. このスクリプトを空のゲームオブジェクト(例:EventTriggerObject)にアタッチします。

3.2 イベントに反応する処理を登録しよう

イベントが発生したときに実行される処理をイベントハンドラと言います。これを登録する方法は2つあります。

3.2.1 インスペクターで登録する方法

  1. イベントハンドラとなるスクリプトを作成 新しいC#スクリプトを作成し、名前をGameManagerとします。
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public void OnPlayerDamaged()
       {
           Debug.Log("プレイヤーがダメージを受けた!");
       }
   }
  1. このGameManagerスクリプトを別のゲームオブジェクト(例:GameManagerObject)にアタッチします。
  2. イベントハンドラをインスペクターで登録
  • EventTriggerObjectを選択し、インスペクターでMy Eventという項目を探します。
  • +ボタンを押して、新しいイベントハンドラを追加します。
  • GameManagerObjectをドラッグ&ドロップして、オブジェクト欄にセットします。
  • 関数を選択するドロップダウンメニューから、GameManager -> OnPlayerDamaged()を選択します。

実行してみましょう

  • プレイモードでスペースキーを押すと、コンソールにプレイヤーがダメージを受けた!と表示されます。

メリット

  • コードを書かずに設定できる
  • 簡単に変更できる

3.2.2 コードで登録する方法

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public EventTrigger eventTrigger;

       void Start()
       {
           // イベントハンドラをコードで登録
           eventTrigger.myEvent.AddListener(OnPlayerDamaged);
       }

       void OnPlayerDamaged()
       {
           Debug.Log("プレイヤーがダメージを受けた!");
       }
   }
  1. インスペクターでeventTriggerを設定
  • GameManagerObjectを選択し、インスペクターでEvent Triggerという項目を探します。
  • EventTriggerObjectをドラッグ&ドロップして、Event Triggerフィールドにセットします。

実行してみましょう

  • プレイモードでスペースキーを押すと、同じようにコンソールにプレイヤーがダメージを受けた!と表示されます。
    2つ表示されることがあったらなぜか?を考えてみましょう

メリット

  • 実行中にイベントハンドラを追加・削除できる
  • より柔軟な設定が可能

3.3 引数つきのイベントを使おう

イベントに情報を渡したい場合、引数つきのイベントを使います。

ステップ1:引数つきのイベントを作成

  1. EventTriggerスクリプトを編集
using UnityEngine;
using UnityEngine.Events;

public class EventTrigger : MonoBehaviour
{
    // Unity2019.3以降ではこのように記述できます
    public UnityEvent<int> onDamaged;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            int damageAmount = 10;
            onDamaged.Invoke(damageAmount); // ダメージ量を渡す
        }
    }
}
  • ジェネリックなUnityEvent<T>のシリアライズがサポートされていないため、インスペクター上で表示されません。
  • この場合、以下のようにカスタムクラスを定義する必要があります。
using UnityEngine;
using UnityEngine.Events;

// 引数つきのUnityEventを定義
[System.Serializable]
public class DamageEvent : UnityEvent<int> { }

public class EventTrigger : MonoBehaviour
{
    public DamageEvent onDamaged;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            int damageAmount = 10;
            onDamaged.Invoke(damageAmount); // ダメージ量を渡す
        }
    }
}

ステップ2:イベントハンドラを作成

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public EventTrigger eventTrigger;

       void Start()
       {
           // 引数つきのイベントハンドラを登録
           eventTrigger.onDamaged.AddListener(ApplyDamage);
       }

       void ApplyDamage(int damage)
       {
           Debug.Log($"プレイヤーが{damage}のダメージを受けた!");
       }
   }

ステップ3:実行してみましょう

  • プレイモードでスペースキーを押すと、プレイヤーが10のダメージを受けた!と表示されます。

4. コリジョンやトリガーを使った独自イベント

ゲーム開発では、オブジェクト同士の衝突(コリジョン)や、トリガー領域への侵入・退出を検知することがよくあります。これらを使って、独自のイベントを作成し、汎用的に活用する方法を紹介します。

4.1 コリジョンイベントの活用

コリジョンとは?

  • コリジョン(Collision)とは、物理的な衝突を検知する機能です。
  • Unityでは、OnCollisionEnterOnCollisionStayOnCollisionExitなどのメソッドでコリジョンイベントを扱います。

コリジョンを使った独自イベントの作成

ステップ1:プレイヤーと敵を用意

  • プレイヤーオブジェクトを作成
    • 3DオブジェクトのCubeを作成し、名前をPlayerに変更します。
    • PlayerRigidbodyコンポーネントを追加します。
  • 敵オブジェクトを作成
    • 3DオブジェクトのCubeを作成し、名前をEnemyに変更します。
    • EnemyRigidbodyコンポーネントを追加し、Is Kinematicにチェックを入れます。
    • EnemyのタグをEnemyに設定します(タグを追加する必要があります)。

ステップ2:コリジョンイベントを作成

  1. 新しいC#スクリプトを作成し、名前をCollisionEventTriggerとします。
  2. CollisionEventTriggerスクリプトをPlayerにアタッチ
  3. CollisionEventTriggerスクリプトを編集
   using UnityEngine;
   using UnityEngine.Events;

   public class CollisionEventTrigger : MonoBehaviour
   {
       public UnityEvent collisionEvent;

       void OnCollisionEnter(Collision collision)
       {
           if (collision.gameObject.CompareTag("Enemy"))
           {
               collisionEvent.Invoke();
           }
       }
   }

ステップ3:イベントハンドラを作成

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public CollisionEventTrigger collisionTrigger;

       void Start()
       {
           collisionTrigger.collisionEvent.AddListener(OnPlayerHitEnemy);
       }

       void OnPlayerHitEnemy()
       {
           Debug.Log("プレイヤーが敵と衝突した!");
           // 追加の処理(例:ライフを減らすなど)をここに書く
       }
   }
  1. インスペクターでcollisionTriggerを設定
  • GameManagerObjectを選択し、Collision TriggerフィールドにPlayerをドラッグ&ドロップします。

ステップ4:実行してみましょう

  • プレイモードでPlayerEnemyに移動させて衝突させると、コンソールにプレイヤーが敵と衝突した!と表示されます。

4.2 トリガーイベントの活用

トリガーとは?

  • トリガー(Trigger)とは、物理演算はせずに領域への侵入や退出を検知する機能です。
  • Unityでは、OnTriggerEnterOnTriggerStayOnTriggerExitなどのメソッドでトリガーイベントを扱います。

トリガーを使った独自イベントの作成

ステップ1:トリガーエリアを作成

  1. トリガーオブジェクトを作成
  • 3DオブジェクトのCubeを作成し、名前をTriggerAreaに変更します。
  • Box ColliderIs Triggerにチェックを入れます。
  • 位置やサイズを調整して、プレイヤーが侵入できるエリアを作ります。

ステップ2:トリガーイベントを作成

  1. 新しいC#スクリプトを作成し、名前をTriggerEventTriggerとします。
  2. TriggerEventTriggerスクリプトをTriggerAreaにアタッチ
  3. TriggerEventTriggerスクリプトを編集
   using UnityEngine;
   using UnityEngine.Events;

   public class TriggerEventTrigger : MonoBehaviour
   {
       public UnityEvent triggerEvent;

       void OnTriggerEnter(Collider other)
       {
           if (other.gameObject.CompareTag("Player"))
           {
               triggerEvent.Invoke();
           }
       }
   }

ステップ3:イベントハンドラを作成

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public CollisionEventTrigger collisionTrigger;
       public TriggerEventTrigger triggerEventTrigger;

       void Start()
       {
           // 既存のイベントハンドラ登録
           collisionTrigger.collisionEvent.AddListener(OnPlayerHitEnemy);

           // 新しいトリガーイベントハンドラ登録
           triggerEventTrigger.triggerEvent.AddListener(OnPlayerEnterArea);
       }

       void OnPlayerHitEnemy()
       {
           Debug.Log("プレイヤーが敵と衝突した!");
       }

       void OnPlayerEnterArea()
       {
           Debug.Log("プレイヤーがエリアに侵入した!");
           // 追加の処理をここに書く
       }
   }
  1. インスペクターでtriggerEventTriggerを設定
  • GameManagerObjectを選択し、Trigger Event TriggerフィールドにTriggerAreaをドラッグ&ドロップします。

ステップ4:実行してみましょう

  • プレイモードでPlayerを操作し、TriggerAreaに侵入すると、コンソールにプレイヤーがエリアに侵入した!と表示されます。

4.3 独自イベントを作成してみよう

コリジョンやトリガーイベントを汎用的に使えるように、独自のイベントクラスを作成してみましょう。

ステップ1:独自のイベントクラスを作成

  1. CustomEventTriggerスクリプトを作成
using UnityEngine;
using UnityEngine.Events;

public class CustomEventTrigger : MonoBehaviour
{
    public UnityEvent<GameObject> onCollisionWithEnemy;

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
        {
            onCollisionWithEnemy.Invoke(collision.gameObject);
        }
    }
}
  1. CustomEventTriggerスクリプトをPlayerにアタッチ

ステップ2:イベントハンドラを作成

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public CustomEventTrigger customEventTrigger;

       void Start()
       {
           customEventTrigger.onCollisionWithEnemy.AddListener(HandleEnemyCollision);
       }

       void HandleEnemyCollision(GameObject enemy)
       {
           Debug.Log($"{enemy.name}と衝突しました!");
           // 敵ごとの処理を行うことができます
       }
   }
  1. インスペクターでcustomEventTriggerを設定
  • GameManagerObjectを選択し、Custom Event TriggerフィールドにPlayerをドラッグ&ドロップします。

ステップ3:実行してみましょう

  • PlayerEnemyに衝突すると、コンソールにEnemyと衝突しました!と表示されます。

イベントをもっと活用しよう

複数のオブジェクトでイベントを共有

  • 複数のプレイヤーや敵がいても、イベントを使って共通の処理を簡単に行えます。
  • 動的に生成されるオブジェクトでも、OnEnableStartでイベントハンドラを登録すればOKです。

例:敵キャラクターが倒されたときにスコアを加算する

ステップ1:敵スクリプトを作成

  1. 新しいC#スクリプトを作成し、名前をEnemyとします。
  2. Enemyスクリプトを作成
  3. スクリプトをEnemyオブジェクトにアタッチします
   using UnityEngine;
   using UnityEngine.Events;

   public class Enemy : MonoBehaviour
   {
       public UnityEvent onDestroyed;

       void OnDestroy()
       {
           onDestroyed.Invoke();
       }
   }

ステップ2:敵をプレハブ化

  1. Enemyオブジェクトをプレハブ化します。
  • EnemyオブジェクトをProjectウィンドウにドラッグ&ドロップします。

ステップ3:敵を生成し、イベントハンドラを登録

  1. GameManagerスクリプトを編集
   using UnityEngine;

   public class GameManager : MonoBehaviour
   {
       public int score = 0;
       public GameObject enemyPrefab;

       void Start()
       {
           // 敵を生成
           GameObject enemyObject = Instantiate(enemyPrefab, new Vector3(0, 0, 0), Quaternion.identity);
           Enemy enemyScript = enemyObject.GetComponent<Enemy>();

           // イベントハンドラを登録
           enemyScript.onDestroyed.AddListener(AddScore);
       }

       void AddScore()
       {
           score += 100;
           Debug.Log("スコアが加算されました。現在のスコア:" + score);
       }
   }
  1. インスペクターでenemyPrefabを設定
  • GameManagerObjectを選択し、Enemy PrefabフィールドにEnemyプレハブをドラッグ&ドロップします。

ステップ4:敵を破壊してみましょう

  • ゲーム内でEnemyオブジェクトを削除(例えば、衝突時にDestroy(enemyObject);を呼び出す)すると、スコアが加算されました。現在のスコア:100と表示されます。

まとめ

  • イベントを使うと、特定のタイミングで処理を実行できて、コードがスッキリします。
  • コリジョンやトリガーを使った独自イベントを作る際には、CompareTagを使ってタグを比較すると効率的です。
  • UnityEventを使って、簡単にイベントを作成できます。
  • イベントハンドラを登録する方法は、インスペクターとコードの2通りあります。
  • 引数つきのイベントを使うと、より多くの情報を渡せます。
  • イベントを使うことで、機能の追加や変更が簡単になり、ゲーム開発が楽しくなります!

最後に

このチュートリアルでは、実際にコードを書きながらイベントの基本から応用までを学びました。イベントを上手に使うことで、コードの再利用性が高まり、複雑な処理も簡潔に書けるようになります。ぜひ、今回学んだことを活かして、魅力的なゲームやアプリを作ってみてくださいね!

Unity,イベント

Posted by hidepon