はじめてのイベントプログラミング:完全チュートリアル
ゲーム開発やアプリケーション制作を始めたばかりの皆さん、プログラミングを進めていく中で「イベント」という言葉を聞いたことがあるでしょうか?イベントは、ユーザーの操作やゲーム内の出来事に応じて特定の処理を実行するための重要な仕組みです。
本チュートリアルでは、初学者の方でも理解しやすいように、イベントの基本から活用方法までを丁寧に解説します。特に、コリジョンやトリガーを使った独自イベントの作り方についても実際にコードを書きながら学んでいきますので、ぜひ一緒に手を動かしてみてください。
イベントってなに?
イベントとは、ゲームやアプリで「何かが起こったときに、そのタイミングで特定の処理を実行する仕組み」のことです。
たとえば…
- ボタンが押されたとき
- キーボードのキーが押されたとき
- 敵とぶつかったとき
- タイマーで時間がきたとき
これらの「きっかけ」に応じて、自動的にプログラムが動いてくれます。
イベントを使わないとどうなるの?
最初はイベントを使わずにプログラムを書いても問題ないかもしれません。でも、機能をどんどん追加していくと、コードがごちゃごちゃになって大変になります。
例:スペースキーが押されたらライフを減らす
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:イベントを作るスクリプトを作成
- 新しいC#スクリプトを作成し、名前を
EventTrigger
とします。 - スクリプトを開き、以下のコードを書きます。
using UnityEngine;
using UnityEngine.Events;
public class EventTrigger : MonoBehaviour
{
// UnityEvent型のイベントを宣言
public UnityEvent myEvent;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// イベントを発生させる
myEvent.Invoke();
}
}
}
- このスクリプトを空のゲームオブジェクト(例:
EventTriggerObject
)にアタッチします。
3.2 イベントに反応する処理を登録しよう
イベントが発生したときに実行される処理をイベントハンドラと言います。これを登録する方法は2つあります。
3.2.1 インスペクターで登録する方法
- イベントハンドラとなるスクリプトを作成 新しいC#スクリプトを作成し、名前を
GameManager
とします。
using UnityEngine;
public class GameManager : MonoBehaviour
{
public void OnPlayerDamaged()
{
Debug.Log("プレイヤーがダメージを受けた!");
}
}
- この
GameManager
スクリプトを別のゲームオブジェクト(例:GameManagerObject
)にアタッチします。 - イベントハンドラをインスペクターで登録
EventTriggerObject
を選択し、インスペクターでMy Event
という項目を探します。+
ボタンを押して、新しいイベントハンドラを追加します。GameManagerObject
をドラッグ&ドロップして、オブジェクト欄にセットします。- 関数を選択するドロップダウンメニューから、
GameManager -> OnPlayerDamaged()
を選択します。
実行してみましょう
- プレイモードでスペースキーを押すと、コンソールに
プレイヤーがダメージを受けた!
と表示されます。
メリット
- コードを書かずに設定できる
- 簡単に変更できる
3.2.2 コードで登録する方法
GameManager
スクリプトを編集
using UnityEngine;
public class GameManager : MonoBehaviour
{
public EventTrigger eventTrigger;
void Start()
{
// イベントハンドラをコードで登録
eventTrigger.myEvent.AddListener(OnPlayerDamaged);
}
void OnPlayerDamaged()
{
Debug.Log("プレイヤーがダメージを受けた!");
}
}
- インスペクターで
eventTrigger
を設定
GameManagerObject
を選択し、インスペクターでEvent Trigger
という項目を探します。EventTriggerObject
をドラッグ&ドロップして、Event Trigger
フィールドにセットします。
実行してみましょう
- プレイモードでスペースキーを押すと、同じようにコンソールに
プレイヤーがダメージを受けた!
と表示されます。
2つ表示されることがあったらなぜか?を考えてみましょう
メリット
- 実行中にイベントハンドラを追加・削除できる
- より柔軟な設定が可能
3.3 引数つきのイベントを使おう
イベントに情報を渡したい場合、引数つきのイベントを使います。
ステップ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:イベントハンドラを作成
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では、
OnCollisionEnter
、OnCollisionStay
、OnCollisionExit
などのメソッドでコリジョンイベントを扱います。
コリジョンを使った独自イベントの作成
ステップ1:プレイヤーと敵を用意
- プレイヤーオブジェクトを作成
- 3DオブジェクトのCubeを作成し、名前を
Player
に変更します。 Player
にRigidbody
コンポーネントを追加します。
- 3DオブジェクトのCubeを作成し、名前を
- 敵オブジェクトを作成
- 3DオブジェクトのCubeを作成し、名前を
Enemy
に変更します。 Enemy
にRigidbody
コンポーネントを追加し、Is Kinematic
にチェックを入れます。Enemy
のタグをEnemy
に設定します(タグを追加する必要があります)。
- 3DオブジェクトのCubeを作成し、名前を
ステップ2:コリジョンイベントを作成
- 新しいC#スクリプトを作成し、名前を
CollisionEventTrigger
とします。 CollisionEventTrigger
スクリプトをPlayer
にアタッチ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:イベントハンドラを作成
GameManager
スクリプトを編集
using UnityEngine;
public class GameManager : MonoBehaviour
{
public CollisionEventTrigger collisionTrigger;
void Start()
{
collisionTrigger.collisionEvent.AddListener(OnPlayerHitEnemy);
}
void OnPlayerHitEnemy()
{
Debug.Log("プレイヤーが敵と衝突した!");
// 追加の処理(例:ライフを減らすなど)をここに書く
}
}
- インスペクターで
collisionTrigger
を設定
GameManagerObject
を選択し、Collision Trigger
フィールドにPlayer
をドラッグ&ドロップします。
ステップ4:実行してみましょう
- プレイモードで
Player
をEnemy
に移動させて衝突させると、コンソールにプレイヤーが敵と衝突した!
と表示されます。
4.2 トリガーイベントの活用
トリガーとは?
- トリガー(Trigger)とは、物理演算はせずに領域への侵入や退出を検知する機能です。
- Unityでは、
OnTriggerEnter
、OnTriggerStay
、OnTriggerExit
などのメソッドでトリガーイベントを扱います。
トリガーを使った独自イベントの作成
ステップ1:トリガーエリアを作成
- トリガーオブジェクトを作成
- 3DオブジェクトのCubeを作成し、名前を
TriggerArea
に変更します。 Box Collider
のIs Trigger
にチェックを入れます。- 位置やサイズを調整して、プレイヤーが侵入できるエリアを作ります。
ステップ2:トリガーイベントを作成
- 新しいC#スクリプトを作成し、名前を
TriggerEventTrigger
とします。 TriggerEventTrigger
スクリプトをTriggerArea
にアタッチ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:イベントハンドラを作成
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("プレイヤーがエリアに侵入した!");
// 追加の処理をここに書く
}
}
- インスペクターで
triggerEventTrigger
を設定
GameManagerObject
を選択し、Trigger Event Trigger
フィールドにTriggerArea
をドラッグ&ドロップします。
ステップ4:実行してみましょう
- プレイモードで
Player
を操作し、TriggerArea
に侵入すると、コンソールにプレイヤーがエリアに侵入した!
と表示されます。
4.3 独自イベントを作成してみよう
コリジョンやトリガーイベントを汎用的に使えるように、独自のイベントクラスを作成してみましょう。
ステップ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);
}
}
}
CustomEventTrigger
スクリプトをPlayer
にアタッチ
ステップ2:イベントハンドラを作成
GameManager
スクリプトを編集
using UnityEngine;
public class GameManager : MonoBehaviour
{
public CustomEventTrigger customEventTrigger;
void Start()
{
customEventTrigger.onCollisionWithEnemy.AddListener(HandleEnemyCollision);
}
void HandleEnemyCollision(GameObject enemy)
{
Debug.Log($"{enemy.name}と衝突しました!");
// 敵ごとの処理を行うことができます
}
}
- インスペクターで
customEventTrigger
を設定
GameManagerObject
を選択し、Custom Event Trigger
フィールドにPlayer
をドラッグ&ドロップします。
ステップ3:実行してみましょう
Player
がEnemy
に衝突すると、コンソールにEnemyと衝突しました!
と表示されます。
イベントをもっと活用しよう
複数のオブジェクトでイベントを共有
- 複数のプレイヤーや敵がいても、イベントを使って共通の処理を簡単に行えます。
- 動的に生成されるオブジェクトでも、
OnEnable
やStart
でイベントハンドラを登録すればOKです。
例:敵キャラクターが倒されたときにスコアを加算する
ステップ1:敵スクリプトを作成
- 新しいC#スクリプトを作成し、名前を
Enemy
とします。 Enemy
スクリプトを作成- スクリプトをEnemyオブジェクトにアタッチします
using UnityEngine;
using UnityEngine.Events;
public class Enemy : MonoBehaviour
{
public UnityEvent onDestroyed;
void OnDestroy()
{
onDestroyed.Invoke();
}
}
ステップ2:敵をプレハブ化
Enemy
オブジェクトをプレハブ化します。
Enemy
オブジェクトをProject
ウィンドウにドラッグ&ドロップします。
ステップ3:敵を生成し、イベントハンドラを登録
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);
}
}
- インスペクターで
enemyPrefab
を設定
GameManagerObject
を選択し、Enemy Prefab
フィールドにEnemy
プレハブをドラッグ&ドロップします。
ステップ4:敵を破壊してみましょう
- ゲーム内で
Enemy
オブジェクトを削除(例えば、衝突時にDestroy(enemyObject);
を呼び出す)すると、スコアが加算されました。現在のスコア:100
と表示されます。
まとめ
- イベントを使うと、特定のタイミングで処理を実行できて、コードがスッキリします。
- コリジョンやトリガーを使った独自イベントを作る際には、
CompareTag
を使ってタグを比較すると効率的です。 UnityEvent
を使って、簡単にイベントを作成できます。- イベントハンドラを登録する方法は、インスペクターとコードの2通りあります。
- 引数つきのイベントを使うと、より多くの情報を渡せます。
- イベントを使うことで、機能の追加や変更が簡単になり、ゲーム開発が楽しくなります!
最後に
このチュートリアルでは、実際にコードを書きながらイベントの基本から応用までを学びました。イベントを上手に使うことで、コードの再利用性が高まり、複雑な処理も簡潔に書けるようになります。ぜひ、今回学んだことを活かして、魅力的なゲームやアプリを作ってみてくださいね!
ディスカッション
コメント一覧
まだ、コメントがありません