メインコンテンツまでスキップ

ゲームイベントの発火

イベントを作成し構成した後、最後のステップはゲームロジックでそれらをトリガーすることです。このページでは、ゲームイベントがどのように機能するか、スクリプトでそれらを発火する方法を示します。

ビジュアルワークフローを完了
  1. ✅ イベントを作成 → Game Event Creator
  2. ✅ アクションを構成 → Game Event Behavior
  3. イベントを発火 ← 現在地

🎯 ゲームイベントの仕組み

ゲームイベントはイベント発火アクション実行を分離します:

従来のアプローチ:

// ❌ 密結合 - ドアのロジックがサウンド、アニメーションなどを知っている
public class Door : MonoBehaviour
{
public AudioSource audioSource;
public Animator animator;
public UIManager uiManager;

public void Open()
{
audioSource.Play();
animator.SetTrigger("Open");
uiManager.ShowNotification("Door opened");
// ロジックが複数の依存関係に分散
}
}

ゲームイベントアプローチ:

// ✅ 疎結合 - ドアは「何かが起こった」ことだけを知る
public class Door : MonoBehaviour
{
[GameEventDropdown]
public GameEvent onDoorOpened;

public void Open()
{
onDoorOpened.Raise(); // アクションはインスペクターで構成
}
}

主な違い: アクション(サウンド、アニメーション、UI)は、スクリプトにハードコードされるのではなく、Event Behaviorで視覚的に構成されます。


📝 基本的な使用法: イベントの発火

ステップ1: スクリプトでイベントを参照

using TinyGiants.GameEventSystem.Runtime;
using UnityEngine;

public class DoorController : MonoBehaviour
{
[GameEventDropdown] // スマートインスペクターピッカー
public GameEvent onDoorOpened;

[GameEventDropdown]
public GameEvent onDoorClosed;

public void OpenDoor()
{
// ドアのロジックをここに
onDoorOpened.Raise(); // イベントをトリガー
}

public void CloseDoor()
{
// ドアのロジックをここに
onDoorClosed.Raise();
}
}

ステップ2: インスペクターでイベントを割り当て

[GameEventDropdown]属性は型安全な検索可能ドロップダウンを提供します:

GameEvent Dropdown

機能:

  • 🔍 ファジー検索: 入力して名前でイベントをフィルタリング
  • 📁 カテゴリ分け: データベースとカテゴリ別にグループ化されたイベント
  • 🔒 型安全性: 互換性のあるイベント型のみを表示
  • クイックアクセス: 手動でアセットをドラッグする必要なし

代替: [GameEventDropdown]なし

標準のpublicフィールドを使用することもできます:

public GameEvent onDoorOpened;  // 標準のScriptableObjectフィールド

インスペクタービュー:

Standard Object Field

ワークフロー:

  1. Projectウィンドウでイベントアセットを見つける(Event Database)
  2. インスペクターフィールドにドラッグ&ドロップ

推奨事項: より良いワークフローのために**[GameEventDropdown]**を使用してください—より速く、型安全です。


🎨 型付きイベント(引数付き)

イベントはアクションにデータを運ぶことができます。

Voidイベント(データなし)

[GameEventDropdown]
public GameEvent onGameStart;

void Start()
{
onGameStart.Raise(); // 引数なし
}

単一引数イベント

[GameEventDropdown]
public GameEvent<float> onHealthChanged;

private float health = 100f;

public void TakeDamage(float damage)
{
health -= damage;
onHealthChanged.Raise(health); // 現在のヘルス値を渡す
}

型安全性: ドロップダウンはGameEvent<float>イベントのみを表示し、型の不一致を防ぎます。


Sender + 引数イベント

[GameEventDropdown]
public GameEvent<GameObject, DamageInfo> onPlayerDamaged;

public void ApplyDamage(DamageInfo damageInfo)
{
// Sender = このGameObject、Args = ダメージ情報
onPlayerDamaged.Raise(this.gameObject, damageInfo);
}

使用例: アクションは誰がイベントをトリガーしたか、どのデータを処理するかを知る必要があります。


🔒 実行中の型安全性

ドロップダウンは、フィールド型に基づいてイベントを自動的にフィルタリングします:

public class ScoreManager : MonoBehaviour
{
[GameEventDropdown]
public GameEvent<int> onScoreChanged; // GameEvent<int>のみを表示

[GameEventDropdown]
public GameEvent<int> onLevelUp; // GameEvent<int>のみを表示

private int score = 0;

public void AddScore(int points)
{
score += points;
onScoreChanged.Raise(score); // 整数スコアを渡す
}
}

ドロップダウンフィルタリング:

GameEvent<int>の利用可能なイベント:
✅ OnScoreChanged (int)
✅ OnLevelUp (int)
✅ OnComboMultiplier (int)
❌ OnPlayerDeath (void) — フィルタリングされた(誤った型)
❌ OnDamage (float) — フィルタリングされた(誤った型)

なぜこれが重要か: 編集時に型エラーをキャッチし、実行時ではありません。


🔄 スケジュールされたイベントのキャンセル

イベントが遅延または繰り返し設定を使用している場合(**Game Event Behavior**で構成)、実行をキャンセルできます:

[GameEventDropdown]
public GameEvent repeatingSoundEvent;

void StartAmbientSound()
{
repeatingSoundEvent.Raise(); // 繰り返しを開始(Behavior構成に基づく)
}

void StopAmbientSound()
{
repeatingSoundEvent.Cancel(); // スケジュールされた実行を停止
}

使用例:

  • プレイヤーがトリガーゾーンを離れる → アンビエントサウンドをキャンセル
  • ゲームが一時停止 → タイミングイベントをキャンセル
  • オブジェクトが破棄される → スケジュールされたアクションをクリーンアップ

🔧 高度: インスペクターリスナーコントロール

めったに必要ありませんが、実行時にインスペクター構成アクションを無効にできます:

[GameEventDropdown]
public GameEvent myEvent;

void DisableCutsceneUI()
{
myEvent.SetInspectorListenersActive(false);
// インスペクターアクションは発火しない、コードリスナーのみ
}

void EnableCutsceneUI()
{
myEvent.SetInspectorListenersActive(true);
// インスペクターアクションが再び発火
}

使用例:

  • カットシーン中にUI更新を一時的に無効化
  • ゲーム状態に基づいてアクションセット間を切り替え

💡 完全なワークフロー例

ビジュアルワークフローを使用して完全なドアシステムを構築しましょう。

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

**Game Event Creator**で:

Event Editor Create

  • OnDoorOpened(voidイベント)を作成
  • OnDoorClosed(voidイベント)を作成

ステップ2: アクションを構成

**Game Event Behavior**で:

Event Behavior Configure

OnDoorOpenedイベント:

  • アクション: AudioSource.PlayOneShot(doorOpenSound)
  • アクション: Animator.SetTrigger("Open")
  • アクション: ParticleSystem.Play()(ダストエフェクト)

OnDoorClosedイベント:

  • アクション: AudioSource.PlayOneShot(doorCloseSound)
  • アクション: Animator.SetTrigger("Close")

ステップ3: スクリプトを書く

using TinyGiants.GameEventSystem.Runtime;
using UnityEngine;

public class DoorController : MonoBehaviour
{
[GameEventDropdown]
public GameEvent onDoorOpened;

[GameEventDropdown]
public GameEvent onDoorClosed;

private bool isOpen = false;

public void ToggleDoor()
{
if (isOpen)
{
isOpen = false;
onDoorClosed.Raise(); // すべてのアクションが自動的に発火
}
else
{
isOpen = true;
onDoorOpened.Raise(); // すべてのアクションが自動的に発火
}
}

// このメソッドは以下から呼び出すことができます:
// - インスペクターのボタンOnClick
// - Collision/Trigger検出
// - 他のゲームシステム
}

ステップ4: インスペクターでイベントを割り当て

Door Inspector Setup

  1. DoorController GameObjectを選択
  2. ドロップダウンを使用してOnDoorOpenedイベントを割り当て
  3. ドロップダウンを使用してOnDoorClosedイベントを割り当て

完了! スクリプトにサウンド、アニメーション、VFX参照なし—すべて視覚的に構成。


🆚 なぜUnityEventsより優れているか?

従来のUnityEventアプローチには、ゲームイベントが解決する制限があります:

従来のUnityEventの制限

// ❌ 問題1: 多くのGameObjectにわたって分散された構成
public class Button1 : MonoBehaviour
{
public UnityEvent onClick; // Button1のインスペクターで構成
}

public class Button2 : MonoBehaviour
{
public UnityEvent onClick; // Button2のインスペクターで構成
}

// ❌ 問題2: すべての使用箇所を見つけるのが難しい
// シーン内のすべてのGameObjectを手動で検索する必要がある

// ❌ 問題3: 中央制御なし
// ボタンサウンドをグローバルに有効/無効化できない

// ❌ 問題4: 重複
// 50個のボタンで同じサウンド/VFXセットアップが繰り返される

ゲームイベントの利点

// ✅ 解決策: すべてのボタンが同じイベントを発火
public class ButtonController : MonoBehaviour
{
[GameEventDropdown]
public GameEvent onButtonClick; // すべてのボタンで同じイベント

public void OnClick()
{
onButtonClick.Raise();
}
}

利点:

機能UnityEventゲームイベント
集中構成❌ GameObjectごと✅ 1つのEvent Behavior
すべての使用箇所を検索❌ 手動検索Event Finder
グローバルコントロール❌ 50個のオブジェクトを変更✅ 1つのイベントを変更
再利用性❌ コピー&ペースト✅ 同じアセットを参照
条件ロジック❌ コードが必要✅ ビジュアル条件ツリー
デバッグ❌ インスペクターのみ✅ フローグラフ視覚化

それぞれを使用するタイミング

UnityEventsを使用:

  • シンプルな一回限りのコールバック(例: チュートリアルボタン)
  • コンポーネント固有のロジック(例: スライダーが独自のラベルを更新)
  • 再利用性が不要

ゲームイベントを使用:

  • 再利用可能なロジック(例: すべてのボタンクリックが同じサウンドを再生)
  • 複雑なシーケンス(例: カットシーン、ドアパズル)
  • 中央制御が必要(例: すべてのUIサウンドをミュート)
  • ビジュアルデバッグが必要(フローグラフ)

❓ トラブルシューティング

ドロップダウンに「Manager Missing」と表示

原因: シーンにGameEventManagerがありません。

解決策:

Unityツールバーから Game Event System を開きます:

Tools > TinyGiants > Game Event System

「Initialize Event System」ボタンをクリックすると、シーンにGame Event Manager GameObject(シングルトン)が作成されます。


ドロップダウンに「No Active Databases」と表示

原因: GameEventManagerにデータベースが割り当てられていません。

解決策:

  1. シーンでGameEventManagerを選択
  2. インスペクター → Databasesセクション
  3. イベントデータベースを追加

ドロップダウンに「No Matching Events」と表示

原因: フィールド型に一致するイベントがありません。

:

[GameEventDropdown]
public GameEvent<string> textEvent; // GameEvent<string>が必要

// しかし、データベースには以下のみがあります:
// - GameEvent (void)
// - GameEvent<int>
// - GameEvent<float>

結果: 一致するイベントなし!

解決策: Game Event Creatorを使用して正しい型のイベントを作成します。


イベントが発火しない

チェックリスト:

  1. ✅ イベントアセットがインスペクターで割り当てられているか?
  2. Raise()が呼び出されているか?(Debug.Logを追加して確認)
  3. ✅ アクションがGame Event Behaviorで構成されているか?
  4. ✅ 条件が満たされているか?(条件ツリーを確認)
  5. ✅ GameEventManagerがシーンにあるか?
ビジュアルワークフロー完了!

これで完全なビジュアルワークフローを学びました:

  1. ✅ Event Creatorでイベントを作成
  2. ✅ Event Behaviorでアクションを構成
  3. ✅ UnityEventsまたはGameEventDropdownでイベントを発火

結果: 疎結合で、保守可能な、デザイナーフレンドリーなゲームロジック!

ビジュアルからコードへ

このページはビジュアルワークフロー(インスペクター割り当てでスクリプト内のイベントを発火)をカバーしています。高度なコード技術(実行時リスナー、条件トリガー、イベントチェーン)については、**Runtime API**を参照してください。