ラムダ式
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]));
}チャレンジ
簡単金庫は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;
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。