Menu
CoddyTech

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]));
}
challenge icon

挑战

简单

在 Start() 中连接保险库的键盘。

  1. 用 for 循环遍历 keys。在循环中,声明 int digit = i + 1;,并将 keys[i] 连接到 () => Press(digit)。
  2. 将 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 在线编辑器