Menu
CoddyTech

ラムダ式

CoddyのUnityジャーニー「本格的なゲームを作る」セクションの一部。レッスン 7/56。

AddListenerは、パラメーターを持たないメソッドを受け取ります。クリック時に、色を受け取るPaint(Color.red)を呼び出すには、その場でメソッドを書きます。() => Paint(Color.red)です。これはラムダ、つまり名前のないメソッドです。()にはパラメーターを記述しますが、ここではありません。=>の後には本体が続きます。1つのステートメント、または複数の場合は{ }で囲んだブロックです。

public Button redButton;
public Button blueButton;
public Button resetButton;
public Renderer lamp;
private int changes;

void Start()
{
    redButton.onClick.AddListener(() => Paint(Color.red));
    blueButton.onClick.AddListener(() => Paint(Color.blue));
    resetButton.onClick.AddListener(() =>
    {
        changes = 0;
        lamp.material.color = Color.white;
    });
}

void Paint(Color color)
{
    lamp.material.color = color;
    changes++;
}

1つのPaintメソッドで両方の色ボタンに対応し、それぞれのラムダが独自の色を渡します。ラムダは、使用する変数をキャプチャします。値をコピーするのではなく、実行時にその変数を読み取ります。リセットのラムダは、クリックされるたびにフィールドchangesを設定します。これはStart()が終了したずっと後のことです。

ループでは落とし穴があります。swatches[i].onClick.AddListener(() => Paint(colors[i]));では、すべてのラムダが同じiをキャプチャします。誰かがクリックする頃にはループが終了し、iはcolors.Lengthと等しくなっているため、すべてのスウォッチでIndexOutOfRangeExceptionが発生します。ループ内で宣言された変数は、ループの反復ごとに新しく作られます。そのため、iを別の変数にコピーして、そのコピーをキャプチャします。

for (int i = 0; i < swatches.Length; i++)
{
    int index = i;
    swatches[i].onClick.AddListener(() => Paint(colors[index]));
}
challenge icon

チャレンジ

簡単

金庫は3桁のコードで開きます。Keypad.csには、画面上のコードに数字を追加し、3桁入力された後にドアを開けるかWrongを表示するPress(int digit)と、ここまでに入力された内容を表示するShowCode()がすでにあります。Start()でボタンを設定しましょう。

  • keysには4つの数字ボタンが順番に格納されています。keys[0]は1、keys[1]は2、keys[2]は3、keys[3]は4を入力します。forループを使って、それぞれにPressを呼び出すラムダ式を設定しましょう。
  • clearButtonにはラムダ式を1つ設定し、ここまでに入力されたコード(entered)を空にして、ShowCode()で表示しましょう。

コードは312です。再生を押して金庫を開き、その後確認を押してください。

自分で試してみよう

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class Keypad : MonoBehaviour
{
    public Button[] keys;
    public Button clearButton;
    public TMP_Text codeText;
    public GameObject door;
    public string secret = "312";
    private string entered = "";

    void Start()
    {
        ShowCode();
        // 各キーを対応する数字を渡す Press に、clearButton をコードのクリア処理に紐付ける
    }

    void Press(int digit)
    {
        entered += digit;
        ShowCode();
        if (entered.Length == 3)
        {
            if (entered == secret)
            {
                door.SetActive(false);
                codeText.text = "Open";
            }
            else
            {
                codeText.text = "Wrong";
            }
            entered = "";
        }
    }

    void ShowCode()
    {
        codeText.text = "Code: " + entered;
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

本格的なゲームを作るのすべてのレッスン