从定义事件,到订阅事件,再到事件触发和处理

概要

这里是一个完整的示例代码,从定义事件,到订阅事件,再到事件触发和处理,并为每一行添加了详细的注释。
例如:

using System;
using UnityEngine;

// 1. 定义 Game 类
public class Game
{
    // 2. 定义一个事件,表示分数变化时的通知。使用 Action<int>,其中 int 表示分数。
    public event Action<int> ScoreChanged;

    // 3. 定义一个变量来存储当前的分数
    private int score;

    // 4. 增加分数的方法
    public void IncreaseScore(int value)
    {
        // 5. 增加分数
        score += value;

        // 6. 如果有任何订阅者订阅了 ScoreChanged 事件,就触发这个事件,并传递当前分数。
        // ScoreChanged?.Invoke(score) 表示如果 ScoreChanged 不为空,则调用它。
        ScoreChanged?.Invoke(score);
    }
}

// 7. 定义 UI 类
public class UI
{
    // 8. 订阅方法,接受一个 Game 类的实例作为参数
    public void Subscribe(Game game)
    {
        // 9. 订阅 Game 类的 ScoreChanged 事件,并将 OnScoreChanged 方法与之关联
        game.ScoreChanged += OnScoreChanged;
    }

    // 10. 当分数变化时会调用此方法,newScore 是事件传递过来的最新分数
    private void OnScoreChanged(int newScore)
    {
        // 11. 在控制台中输出当前的分数,以模拟更新 UI 的过程
        Debug.Log("New score: " + newScore);
    }
}

// 12. 示例脚本,放在 Unity 场景中的某个 GameObject 上运行
public class GameController : MonoBehaviour
{
    // 13. 定义 Game 和 UI 的实例
    private Game game;
    private UI ui;

    // 14. Unity 的 Start 方法,当场景开始时调用
    void Start()
    {
        // 15. 创建 Game 和 UI 类的实例
        game = new Game();
        ui = new UI();

        // 16. 让 UI 类的实例订阅 game 的 ScoreChanged 事件
        ui.Subscribe(game);

        // 17. 模拟增加分数,每次调用都会触发 ScoreChanged 事件
        game.IncreaseScore(10); // 分数增加 10,触发事件
        game.IncreaseScore(20); // 分数增加 20,触发事件
    }
}

逐行解释:

定义 Game 类,它代表游戏逻辑。

定义一个事件 ScoreChanged,类型为 Action,其中 int 参数表示分数。这个事件允许其他类订阅并接收分数变化的通知。

定义 score 变量用于存储当前的分数。

定义 IncreaseScore 方法,用于增加分数。

调用时,将传入的 value 加到 score 上。

使用 ScoreChanged?.Invoke(score) 触发事件,通知所有订阅者分数已经改变,并传递新的分数。

定义 UI 类,它负责显示分数。

Subscribe 方法,接受一个 Game 实例,将其 ScoreChanged 事件与 UI 的 OnScoreChanged 方法关联。

使用 += 将 OnScoreChanged 方法订阅到 game 的 ScoreChanged 事件中。

OnScoreChanged 方法,当 ScoreChanged 事件触发时,接收新的分数并执行相应逻辑。

在 Unity 的控制台输出新的分数,模拟 UI 更新。

GameController 类是 Unity 中用于测试事件订阅与触发的控制脚本。

定义 Game 和 UI 的实例变量。

Unity 的 Start 方法会在游戏开始时调用。

创建 Game 和 UI 的实例。

调用 ui.Subscribe(game),使 UI 订阅 game 的 ScoreChanged 事件。

调用 game.IncreaseScore(),模拟分数变化,触发事件。

整体流程:

当 IncreaseScore 方法被调用时,score 值会更新。
然后 ScoreChanged?.Invoke(score) 触发事件。
任何订阅了 ScoreChanged 事件的方法(在本例中是 UI 类的 OnScoreChanged 方法)都会被调用,并接收到新的 score。
UI 类的 OnScoreChanged 方法会处理分数变化并在控制台显示出来。

技术细节

Action是什么:

Action 是 .NET 框架中的一个委托类型,位于 System 命名空间中。它用于定义一个不返回值的委托,并可以接受0到16个输入参数。委托是一种引用方法的类型,可以将方法作为参数传递给其他方法,或用于定义事件等。

Action 的基本特点:

没有返回值:Action 委托用于表示不返回值的函数(类似于 void 方法)。
最多接受 16 个参数:可以根据需要定义不同参数数量的 Action 类型,比如没有参数的 Action,或者最多有 16 个参数的 Action<T1, T2, …, T16>。
常用于事件和回调:Action 常用于事件系统中,作为回调函数。

常见用法:

1. 无参数的 Action

Action myAction = () => { Console.WriteLine(“Hello, Action!”); };
myAction(); // 输出:Hello, Action!

解释:Action 是一个不接受参数的委托,在调用时执行 Console.WriteLine。

2. 带参数的 Action

Action myActionWithParam = (x) => { Console.WriteLine("Value: " + x); };
myActionWithParam(5); // 输出:Value: 5

解释:Action 表示接受一个 int 参数的委托。在调用时传递了参数 5。

在事件系统中的使用:

在前面的例子中,我们使用了 Action 来表示 ScoreChanged 事件:
public event Action ScoreChanged;
这表示 ScoreChanged 是一个事件,订阅者在触发事件时会接收到一个 int 类型的参数(在这个例子中是 newScore),但不会返回任何值。这样,我们可以定义事件并将方法绑定到该事件上,当事件触发时调用这些方法。

小结

Func vs. Action

Action:表示不返回值的委托。
Func:表示有返回值的委托,最后一个泛型参数是返回值类型。
例如,Func<int, string> 表示接受一个 int 参数并返回一个 string 值的方法,而 Action 只接受一个 int 参数并且没有返回值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值