问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

闭包在C#和Unity开发中的应用

创作时间:
作者:
@小白创作中心

闭包在C#和Unity开发中的应用

引用
1
来源
1.
https://www.cnblogs.com/Firepad-magic/p/18666242

闭包(Closure)是编程中一个重要的概念,特别是在使用C#和Unity进行开发时。本文将详细介绍闭包的基本概念、在Unity开发中的常见应用场景以及使用闭包时需要注意的事项。

闭包的基本概念

闭包是指一个函数可以捕获和记住它的作用域(上下文)中的变量,即使这个函数已经在其原始作用域之外被调用。在C#中,匿名方法和Lambda表达式通常会创建闭包。闭包允许方法捕获局部变量并在稍后某个时刻使用这些变量。

闭包示例

闭包的一个常见问题是变量捕获。例如,在下面的代码中,闭包捕获的是变量i的引用,而不是当前值,导致后续输出都是最后一个i的值:

为了避免这个问题,可以通过创建局部变量temp,确保闭包捕获的是变量的值而不是引用:

Unity开发中常见的闭包场景

1. 延迟任务(例如协程)

闭包可以用于在延迟执行中捕获当前上下文变量:

void Start()
{
    for (int i = 5; i < 10; i++)
    {
        StartCoroutine(DelayedLog(x => i, i * 0.5f));//i被匿名方法捕获,延迟调用后i始终为10
    }
}
System.Collections.IEnumerator DelayedLog(Func<int,int> func, float delay)
{
    yield return new WaitForSeconds(delay);
    Debug.Log($"Delayed index: {func.Invoke(0)}");//prints: Delayed index: 10
}

2. 动态事件绑定

Unity中的按钮事件或自定义事件监听器经常会用到闭包:

using UnityEngine;
using UnityEngine.UI;
public class ButtonClosureExample : MonoBehaviour
{
    public Button buttonPrefab;
    public Transform buttonParent;
    void Start()
    {
        for (int i = 0; i < 5; i++)
        {
            Button newButton = Instantiate(buttonPrefab, buttonParent);
            newButton.GetComponentInChildren<Text>().text = $"Button {index}";
            newButton.onClick.AddListener(() => Debug.Log($"Button {i} clicked"));
        }
    }
}

在这个例子中,会生成5个Button0~4的按钮,但是点击时输出的始终为Button 5 clicked

3. 异步任务(例如UnityWebRequest或异步加载)

在异步操作中,闭包可以帮助将参数传递给回调:

using UnityEngine;
using UnityEngine.Networking;
public class AsyncClosureExample : MonoBehaviour
{
    void Start()
    {
        string[] urls = { "https://example.com/file1", "https://example.com/file2" };
        foreach (string url in urls)
        {
            StartCoroutine(DownloadData(url));
        }
    }
    System.Collections.IEnumerator DownloadData(string url)
    {
        UnityWebRequest request = UnityWebRequest.Get(url);
        yield return request.SendWebRequest();
        if (request.result == UnityWebRequest.Result.Success)
        {
            Debug.Log($"Downloaded from {url}: {request.downloadHandler.text}");
        }
        else
        {
            Debug.LogError($"Failed to download from {url}: {request.error}");
        }
    }
}

这里的url是通过闭包捕获的,每个协程实例会记住自己的URL,即使下载任务是异步的。

总结

在Unity开发中,闭包是一种强大的工具,尤其在事件、协程、异步任务中非常有用。然而,使用闭包时需要小心捕获变量的行为,避免产生难以调试的错误。

本文原文来自博客园

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号