Lambdas
Part of the Building Real Games section of Coddy's Unity journey. Lesson 7 of 60.
AddListener takes a method with no parameters. To make a click call Paint(Color.red), which takes a color, write the method on the spot: () => Paint(Color.red). That is a lambda, a method with no name. The () holds its parameters, none here, and after => comes its body: one statement, or a block in { } for several:
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++;
}One Paint method serves both color buttons, each lambda passing its own color. A lambda captures the variables it uses: it does not copy their values, it reads them when it runs. The reset lambda sets the field changes each time it is clicked, long after Start() has ended.
That catches you in a loop. With swatches[i].onClick.AddListener(() => Paint(colors[i])); every lambda captures the same i, and by the time anyone clicks, the loop has ended with i equal to colors.Length: every swatch throws IndexOutOfRangeException. A variable declared inside the loop is a new one each time round, so copy i into one and capture the copy:
for (int i = 0; i < swatches.Length; i++)
{
int index = i;
swatches[i].onClick.AddListener(() => Paint(colors[index]));
}Challenge
EasyHook up the vault's keypad in Start().
- Loop over
keyswithfor. In the loop, declareint digit = i + 1;and hookkeys[i]to() => Press(digit). - Hook
clearButtonto one lambda that setsentered = ""and callsShowCode().
Press Play and type 3, 1, 2: the screen reads Open. Then Check.
Try it yourself
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();
// Hook each key to Press with its digit, and clearButton to clearing the code
}
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;
}
}
All lessons in Building Real Games
2Buttons and Screens
Buttons and onClickLambdasWiring in the InspectorPanels On and OffHealth BarsRecap: Upgrade Shop5Saving with PlayerPrefs
Save a NumberLoad with a DefaultHigh ScoreSave SettingsRecap: Coins in the Bank3The Game Manager
One Script Runs the GameThe SingletonGame StatesSwitching on the StateRecap: Round Manager6Project: Endless Runner
Three LanesObstacles Ahead9The New Input System
Two Input SystemsKeyboard and MousePressed This FrameInput ActionsRecap: Input SwapPractice on your own: Unity playground