コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】シングルキャストデリゲートを実現する

/// <summary>
/// スコアを管理するクラス
/// </summary>
public sealed class Score
{
    private int mValue;

    /// <summary>
    /// 値を取得または設定します
    /// </summary>
    public int Value
    {
        get { return mValue; }
        set 
        {
            mValue = value;
            
            // 値が変更された時にイベントを実行します
            if ( mChanged != null )
            {
                mChanged();
            }
        }
    }

    /// <summary>
    /// 値が変更された時に呼び出されます
    /// </summary>
    public event Action mChanged;
}
/// <summary>
/// スコアの UI を管理するクラス
/// </summary>
public sealed class ScoreUI : MonoBehaviour
{
    /// <summary>
    /// 初期化される時に呼び出されます
    /// </summary>
    private void Awake()
    {
        // ゲームマネージャーからスコアを管理するインスタンスを取得します
        var score = GameManager.Instance.Score;
        
        // ScoreUI がアタッチされているゲームオブジェクトから
        // UILabel のコンポーネントを取得します
        var uiLabel = GetComponent<UILabel>();

        // スコアが変更された時にテキストの表示を変更します
        score.mChanged += () => uiLabel.text = score.Value.ToString();
    }
}

例えばアクションゲームを制作していて、スコアや体力の値が変わった時に
ゲージやテキストの表示を変更したい場合に僕はよくイベントを使用します

イベントを使用すると値が変更された時に登録した処理が呼び出されるので
毎フレームスコアや体力の値を確認する必要がなく効率的です

ただ、イベントは複数の関数を登録できるのですが
ときどき 1 つだけしか関数を登録できないようにしたい時があります

その時はイベントではなくpublicのsetアクセサのみを持つデリゲートを使用します

public Action mChanged { private get; set; }
score.mChanged += () => uiLabel.text = score.Value; // エラー
score.mChanged = () => uiLabel.text = score.Value; // OK