Unity C#事件委托疑问解答

Unity一个委托的案例

 using UnityEngine;

public class DelegateExample : MonoBehaviour
{
    // 定义委托类型
    public delegate void OnButtonClickDelegate();

    // 声明委托事件
    public static event OnButtonClickDelegate OnButtonClick;

    private void Update()
    {
        // 模拟按钮点击事件
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 触发委托事件
            if (OnButtonClick != null)
            {
                OnButtonClick();
            }
        }
    }
}

public class EventListener : MonoBehaviour
{
    private void Start()
    {
        // 注册监听委托事件的方法
        DelegateExample.OnButtonClick += HandleButtonClick;
    }

    private void OnDestroy()
    {
        // 取消注册监听委托事件的方法
        DelegateExample.OnButtonClick -= HandleButtonClick;
    }

    private void HandleButtonClick()
    {
        Debug.Log("Button clicked!");
    }
}

二、委托在Unity中的常见用途之一是实现事件系统。以下是一个使用委托实现简单事件系统的示例

using UnityEngine;
using System;

public class EventSystemExample : MonoBehaviour
{
    // 定义委托类型
    public delegate void GameEventHandler();

    // 声明事件
    public static event GameEventHandler OnGameStart;
    public static event GameEventHandler OnGameOver;

    private void Update()
    {
        // 模拟游戏开始事件
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 触发游戏开始事件
            if (OnGameStart != null)
            {
                OnGameStart();
            }
        }

        // 模拟游戏结束事件
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            // 触发游戏结束事件
            if (OnGameOver != null)
            {
                OnGameOver();
            }
        }
    }
}

public class GameUI : MonoBehaviour
{
    private void Start()
    {
        // 注册监听游戏开始事件的方法
        EventSystemExample.OnGameStart += HandleGameStart;

        // 注册监听游戏结束事件的方法
        EventSystemExample.OnGameOver += HandleGameOver;
    }

    private void OnDestroy()
    {
        // 取消注册监听游戏开始事件的方法
        EventSystemExample.OnGameStart -= HandleGameStart;

        // 取消注册监听游戏结束事件的方法
        EventSystemExample.OnGameOver -= HandleGameOver;
    }

    private void HandleGameStart()
    {
        Debug.Log("Game started!");
    }

    private void HandleGameOver()
    {
        Debug.Log("Game over!");
    }
}

public class GameManager : MonoBehaviour
{
    private void OnEnable()
    {
        // 注册监听游戏开始事件的方法
        EventSystemExample.OnGameStart += HandleGameStart;

        // 注册监听游戏结束事件的方法
        EventSystemExample.OnGameOver += HandleGameOver;
    }

    private void OnDisable()
    {
        // 取消注册监听游戏开始事件的方法
        EventSystemExample.OnGameStart -= HandleGameStart;

        // 取消注册监听游戏结束事件的方法
        EventSystemExample.OnGameOver -= HandleGameOver;
    }

    private void HandleGameStart()
    {
        Debug.Log("GameManager: Game started!");
    }

    private void HandleGameOver()
    {
        Debug.Log("GameManager: Game over!");
    }
}

三、什么情况下用委托呢

1、事件处理:委托允许你创建和触发事件,让其他对象能够注册和处理特定的事件。这种情况下,委托充当事件的触发器。

2、回调函数:委托可以用作回调函数的机制,允许你将一个方法作为参数传递给另一个方法,以便在需要时调用。

3、插件系统:委托可用于构建插件系统,其中主程序可以定义特定的委托来允许插件注册其自定义行为。

4、多播委托:多播委托允许将多个方法绑定到同一个委托实例,然后一次性触发多个方法。这在需要一次性通知多个观察者或执行多个处理逻辑的情况下很有用。

5、异步编程:在异步编程中,委托可以与异步操作一起使用,例如使用委托来处理异步操作完成时的回调。

总之,委托是一种强大的机制,用于实现回调、事件处理、插件系统和异步编程等情况。它提供了一种灵活和可扩展的方式来实现代码的解耦和灵活性。在需要将方法作为参数传递、触发事件或实现回调机制的情况下,委托是一个非常有用的工具。

四、那什么时候用事件

事件是委托的一种特殊形式,用于在对象之间实现松耦合的通信机制。以下是一些适合使用事件的情况:

1、发布/订阅模式:事件常用于实现发布/订阅模式,其中一个对象(发布者)触发事件,而其他对象(订阅者)订阅并接收事件通知。这种模式非常适合实现观察者模式,其中发布者和订阅者之间不直接依赖彼此,提供了更松散的耦合。

2、UI交互:在用户界面中,事件用于处理按钮点击、菜单选择、输入事件等。当用户与界面进行交互时,事件可用于触发相应的操作或更新界面。

3、游戏开发:在游戏开发中,事件常用于处理游戏中的各种事件,如游戏开始、游戏结束、碰撞事件、触发器事件等。通过使用事件,可以实现游戏中的对象间通信和协作。

4、插件系统:事件可用于实现插件系统,其中核心应用程序定义一系列事件,而插件可以订阅这些事件以提供自定义行为。这种方式可以实现灵活的扩展和定制。

5、异步编程:在异步编程中,事件常用于处理异步操作的完成通知。当异步操作完成时,触发相应的事件,让其他部分能够响应和处理完成事件。

总之,事件适合于需要实现对象之间的松耦合通信和响应的场景。它提供了一种清晰、可扩展和灵活的方式来处理各种情况下的事件驱动行为。在需要实现观察者模式、用户界面交互、游戏开发、插件系统和异步编程等场景下,事件是一个非常有用的机制。

五、基本是能用事件就忽略委托吗

在大多数情况下,使用事件比直接使用委托更为方便和适合。事件提供了更高层次的抽象和封装,使代码更易读、维护和扩展。因此,如果你可以使用事件来实现所需的功能,那么推荐使用事件而不是直接使用委托。

然而,有时候直接使用委托可能更加合适。以下是一些情况下可能选择使用委托而不是事件的场景:

1、需要频繁地添加或移除回调函数:如果你的代码需要在多个地方频繁地添加或移除回调函数,而不需要其他事件处理的功能(如事件触发控制、订阅者权限控制等),那么直接使用委托可能更加简洁和高效。

2、需要手动触发回调:事件通常是由特定的条件或操作触发的,而委托可以手动调用。如果你需要手动触发回调函数而不受特定条件限制,那么直接使用委托可能更适合。

3、需要更灵活的调用方式:委托可以以多种方式调用,包括同步调用、异步调用、多线程调用等。如果你需要更灵活的调用方式,可以选择直接使用委托。

总结起来,尽管事件是委托的一种特殊形式,并且在大多数情况下推荐使用事件,但在某些特定情况下直接使用委托可能更加适合。根据你的具体需求和场景,可以选择使用事件或直接使用委托来实现回调功能。

六、事件处理时选择用事件还是委托

在事件处理时,通常会使用事件而不是直接使用委托。这是因为事件提供了更高层次的抽象和封装,使代码更易读、维护和扩展。以下是选择使用事件而不是委托的几个原因:

封装和安全性:事件允许你明确指定事件的触发条件和订阅者的权限。通过使用事件,你可以定义公共的事件访问器(add/remove)并对事件的触发进行控制,防止未经授权的对象触发事件或订阅事件。

扩展性:使用事件可以更容易地扩展和修改事件处理逻辑。你可以添加或移除订阅者而不会影响事件的触发代码,从而实现更灵活的代码组织和模块化。

代码可读性:事件提供了一种直观的方式来表示和使用事件,使代码更易于理解和维护。事件的语义更加清晰,让其他开发人员更容易理解事件的作用和用法。

工具支持:使用事件时,IDE和编辑器通常提供更好的工具支持。你可以方便地查看和导航到事件的订阅者列表,以及快速生成事件触发代码。

尽管委托可以直接用于事件处理,但使用事件可以提供更高级别的抽象和更好的代码组织。委托更适合用于一对一的回调关系,而事件更适合用于一对多的事件通知和响应关系。因此,除非有特殊需求,一般建议在事件处理时选择使用事件而不是直接使用委托。

七、回调函数是什么

回调函数实际上是由另一个函数来调用的函数。

在传统的函数调用中,函数A调用函数B,函数B执行完毕后返回到函数A。而在回调函数中,函数A将函数B作为参数传递给函数C,并在适当的时机由函数C来调用函数B。
回调函数是指将一个函数作为参数传递给另一个函数,并在需要的时候由另一个函数调用的函数。在编程中,回调函数常用于实现回调机制,允许在某个特定事件发生或条件满足时执行自定义的逻辑。
回调函数的特点是它们不是直接由程序的主逻辑调用,而是由某个特定的事件、操作或条件触发后间接调用。通过将回调函数作为参数传递给其他函数,可以将程序的控制权交给调用方,使其可以在合适的时机执行自定义的逻辑。

八、观察者模式是什么

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,其依赖的多个对象都能够自动收到通知并进行相应的更新。

在观察者模式中,有两种主要角色:

Subject(主题):也称为被观察者或可观察者,它是一个具有状态的对象。它维护了一个观察者列表,并提供了方法来添加、移除和通知观察者。当主题的状态发生改变时,它会遍历观察者列表并调用观察者的更新方法。

Observer(观察者):观察者是依赖于主题的对象,它定义了一个更新方法,用于接收主题状态的变化通知。当观察者接收到通知时,它可以根据主题的状态进行相应的处理或更新。

观察者模式的优点在于解耦了主题和观察者之间的依赖关系。主题并不需要知道具体的观察者,它只需要知道观察者接口,并将通知发送给所有注册的观察者。这样,可以方便地增加、移除或替换观察者,而无需修改主题的代码。

观察者模式常用于事件驱动的系统、GUI界面、发布-订阅模型等场景,其中一个对象的状态变化可能需要通知到多个其他对象。通过使用观察者模式,可以实现松耦合的设计,增加系统的灵活性和可维护性。

using System;
using UnityEngine;

// 主题类,负责通知观察者
public class Subject : MonoBehaviour
{
    public event Action OnStateChanged; // 定义事件

    private int state;

    public int State
    {
        get { return state; }
        set
        {
            state = value;
            NotifyObservers(); // 通知观察者状态变化
        }
    }

    private void NotifyObservers()
    {
        if (OnStateChanged != null)
        {
            OnStateChanged(); // 调用事件
        }
    }
}

// 观察者类,响应主题状态变化
public class Observer : MonoBehaviour
{
    private Subject subject;

    private void Start()
    {
        subject = FindObjectOfType<Subject>();
        subject.OnStateChanged += HandleStateChanged; // 订阅事件
    }

    private void HandleStateChanged()
    {
        Debug.Log("Observer: State changed to " + subject.State);
    }
}

// 测试代码
public class TestObserverPattern : MonoBehaviour
{
    private void Start()
    {
        Subject subject = FindObjectOfType<Subject>();

        // 创建两个观察者对象
        Observer observer1 = gameObject.AddComponent<Observer>();
        Observer observer2 = gameObject.AddComponent<Observer>();

        subject.State = 1; // 改变主题状态,触发通知

        subject.OnStateChanged -= observer2.HandleStateChanged; // 取消一个观察者的订阅

        subject.State = 2; // 改变主题状态,触发通知
    }
}

Subject 类是主题类,负责维护状态并通知观察者。它声明了一个事件 OnStateChanged,当状态改变时会触发该事件。Observer 类是观察者类,它订阅主题的 OnStateChanged 事件,并在事件发生时执行相应的逻辑。

在 TestObserverPattern 类中,我们创建了一个主题对象 subject 和两个观察者对象 observer1 和 observer2。首先,我们改变主题的状态并触发通知,观察者对象会收到通知并输出状态变化的信息。然后,我们取消一个观察者的订阅,再次改变主题的状态,此时只有一个观察者收到通知。

通过使用观察者模式,我们可以实现主题与观察者之间的松耦合,主题只需要关注自身状态的维护,而观察者只需要关注状态变化的通知。这样可以使代码更加灵活、可扩展和可维护。

~~

在观察者模式中,一个观察者的状态改变不会直接影响其他观察者的状态。每个观察者都是独立的实体,它们之间相互独立地响应主题状态的变化。 当主题的状态发生改变时,它会通知所有注册的观察者,每个观察者根据自身的逻辑进行相应的处理。观察者之间并没有直接的相互影响或依赖关系。

~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值