Unity事件模型机制解析

事件处理系统是一个非常强大的工具,它使得你可以创建低耦合的代码,这对于大型和复杂的程序是非常重要的。

委托和事件紧密相关。看本文之前强烈建议先看上文C#自定义委托Delegate详解

简而言之,委托是一种特殊的类型,可以用来封装方法,而事件则是一种特殊的委托,提供了一种发布/订阅机制,允许一个对象通知其他对象发生了特定的事情。

事件是一种类型成员。

事件的核心功能就是通知。

快速预览

在教程的开始,我们简单地利用自定义事件机制编写一个demo。

自定义一个事件

例子1:玩家类

这是一个RPG游戏的Player类,当玩家的健康值改变,就触发一个事件。

Player类定义一个委托和事件:

public class Player : MonoBehaviour{
    public delegate void HealthChangedDelegate(int currentHealth);
    public event HealthChangedDelegate OnHealthChanged;

    private int health;
    public int Health{
        get { return health; }
        set{
            health = value;
            OnHealthChanged?.Invoke(health);
        }
    }
}

这个例子中,创建了一个名为HealthChangedDelegate的委托,它接受一个整数参数(当前的健康值)。然后,我们创建了一个名为OnHealthChanged的事件,这个事件会在健康值改变时被触发。

接下来,创建一个其他类UIManager,让这个类订阅Player类的事件。当健康值改变,更新UI显示:

public class UIManager : MonoBehaviour{
    public Player player;

    private void Start(){
        player.OnHealthChanged += UpdateHealthDisplay;
    }

    private void UpdateHealthDisplay(int currentHealth){
        Debug.Log("Health: " + currentHealth);
    }
}

例子2:玩家得分

假设在你的游戏中,玩家可以得分,每当玩家得分时,你希望更新UI显示。这可以通过创建一个自定义事件来实现。

using UnityEngine;
public class UIManagers : MonoBehaviour
{
    public static UIManagers instance;
    public Player player;

    private void Awake(){
        if(instance == null){
            instance = this;
        }else
            if(instance != this)
                Destroy(gameObject);
        DontDestroyOnLoad(gameObject);
    }

    private void Start()
    {
        player.OnScoreChanged += UpdateScoreDisplay;
    }

    private void UpdateScoreDisplay(int currentScore)
    {
        Debug.Log("Score: " + currentScore);
    }
}
using UnityEngine;
public class Player : MonoBehaviour
{
    public delegate void ScoreChangedDelegate(int currentScore);
    public event ScoreChangedDelegate OnScoreChanged;

    private int score;

    public int Score
    {
        get { return score; }
        set
        {
            score = value;
            OnScoreChanged?.Invoke(score);
        }
    }
}

Unity事件模型机制解析

Unity的UI事件

例子1:按钮按下

在Unity的UI系统中,可以使用事件来处理按钮点击。例如,你可以创建一个ButtonHandler类,当按钮被点击时,执行某个操作:

using UnityEngine;
using UnityEngine.UI;

public class ButtonHandler : MonoBehaviour
{
    public Button myButton;

    private void Start()
    {
        myButton.onClick.AddListener(OnButtonClick);
    }

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

Unity的输入事件

例子1:空格检测

Unity的输入系统提供了一套事件模型,可以用来处理键盘、鼠标和触摸输入。例如,你可以创建一个InputHandler类,当玩家按下某个键时,执行某个操作:

using UnityEngine;

public class InputHandler : MonoBehaviour{
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("Space key pressed!");
        }
    }
}

事件模型的五大部分

下面是一个例子:假设你有一个按钮(Button)在你的游戏中,当玩家点击这个按钮时,你希望在游戏中触发一个特定的行为。例如,打开一个菜单,或者使玩家的角色跳跃。你可以为这个按钮添加一个事件监听器,当按钮被点击时,事件监听器就会触发并执行你定义的方法。

简化上述例子:我(类)有一个事件(成员),同时也有另一群人(类)订阅了我的事件。此时我的事件发生了,那一群人(类)就会被通知到。被通知的人(类)就会根据我通知里的「事件参数」,作出相应。

Unity事件模型主要包括以下五个部分:

  1. EventSystem 组件:EventSystem 组件是所有事件交互的中心。在场景中通常只有一个EventSystem。EventSystem管理着在场景中的所有输入(Input)和事件(Event)。
  2. StandaloneInputModule/TouchInputModule 组件:这些输入模块负责处理特定类型的输入。例如,StandaloneInputModule 处理鼠标和键盘输入,TouchInputModule 处理触摸屏输入。
  3. 事件(Event):事件是系统中发生的特定的行为或动作,例如点击按钮,滑动滚动条等。
  4. 事件处理接口(Event Handler Interfaces):这些接口定义了一个类需要实现哪些方法才能处理特定的事件。例如,IPointerClickHandler 接口定义了一个方法 OnPointerClick,任何实现了这个接口的类都可以处理指针点击事件。
  5. 事件监听器(Event Listeners):事件监听器是实现了事件处理接口的对象。当一个事件发生时,事件监听器会通过实现的事件处理接口中的方法来处理事件。

这就是Unity事件模型的主要组成部分,以及它们如何一起工作来处理用户输入和游戏事件。

评论区 0