Lambda 表达式
本课属于 Coddy Unity 学习旅程的“打造真正的游戏”单元。第 7 课,共 60 课。
AddListener 接受一个没有参数的方法。要让点击调用需要颜色的 Paint(Color.red),就在这里编写方法:() => Paint(Color.red)。这就是lambda 表达式,一种没有名称的方法。() 中放的是它的参数,这里没有参数;=> 后面是它的主体:一条语句,或者用 { } 括起来的代码块,其中可以有多条语句:
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++;
}两个颜色按钮共用一个 Paint 方法,每个 lambda 都会传入各自的颜色。lambda 会捕获它使用的变量:它不会复制变量的值,而是在运行时读取这些值。每次点击重置按钮时,重置 lambda 都会设置字段 changes,即使此时 Start() 早已结束。
在循环中就容易遇到这个问题。使用 swatches[i].onClick.AddListener(() => Paint(colors[i])); 时,每个 lambda 捕获的都是同一个 i。等到有人点击时,循环已经结束,i 的值等于 colors.Length,因此每个色块都会抛出 IndexOutOfRangeException。每次循环都会新建一个在循环内部声明的变量,所以要把 i 复制到一个变量中,再捕获这个副本:
for (int i = 0; i < swatches.Length; i++)
{
int index = i;
swatches[i].onClick.AddListener(() => Paint(colors[index]));
}挑战
简单在 Start() 中连接保险库的键盘。
- 用
for循环遍历keys。在循环中,声明int digit = i + 1;,并将keys[i]连接到() => Press(digit)。 - 将
clearButton连接到一个 lambda,该 lambda 将entered = "",并调用ShowCode()。
按“开始”,然后输入 3、1、2:屏幕上会显示 Open。然后点击“检查”。
亲手试试
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;
}
}
打造真正的游戏中的所有课
自己练习: Unity 在线编辑器