Unity简单事件中心

简介

在Unity游戏开发中我们会遇到很多基于事件的交互,比如玩家拾取了某件物品、做了某件事,这些事件可能会造成一些后续效果,那么我们就要对能够造成后续效果的脚本传递对应的消息。当然就是通过传递事件来实现,那么我们就需要一个公共的事件中心来实现对事件触发、传递的功能。

事件管理类

这里使用单例模式来实现事件中心类,包含一个使用事件名存储对应事件的事件字典和私有的构造方法,具体可以参考下面的代码:

public class MyEventManager
    {
        private static MyEventManager _instance;

        // public static MyEventManager Instance
        // {
        //     get { return instance ??= new MyEventManager(); }
        // }
		
		// 静态的属性Instance,提供给外部调用对应的实例
        public static MyEventManager Instance => _instance ??= new MyEventManager();

        private readonly Dictionary<string, IEventInfo> _eventDic;

        // 私有无参构造函数,防止外部调用构造函数
        private MyEventManager()
        {
            _eventDic = new Dictionary<string, IEventInfo>();
        }
    }

添加事件

需要传入事件名,以及对应的回调。就是你希望触发这个时间后能够干些什么:

		// 添加无参数回调
        public void AddEventListener(string eventName, UnityAction action)
        {
        	// 检查事件字典中是否存在对应事件
            if (_eventDic.ContainsKey(eventName))
            {
            	// 如果存在对应事件,则将回调函数添加到委托的调用列表中
                (_eventDic[eventName] as EventInfo).Actions += action;
            }
            else
            {
            	// 如果不存在对应事件,则将此事件添加到事件字典中
                _eventDic.Add(eventName, new EventInfo(action));
            }
        }
		// 添加有参数回调
        public void AddEventListener<T>(string eventName, UnityAction<T> action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions += action;
            }
            else
            {
                _eventDic.Add(eventName, new EventInfo<T>(action));
            }
        }

触发事件

传入事件名来触发对应的事件

		// 无参数的触发
        public void EventTrigger(string eventName)
        {
            if (_eventDic.ContainsKey(eventName))
            {
            	// 触发委托,依次调用委托列表内注册的函数
                (_eventDic[eventName] as EventInfo).Actions?.Invoke();
            }
        }

		// 带参数的触发
        public void EventTrigger<T>(string eventName, T info)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions?.Invoke(info);
            }
        }

如果需要的参数不止一个,可以通过实现带多参数UnityAction的EventInfo类,或者将你需要的参数作为一个类的字段成员包裹起来,当做一个参数来用下面的EventInfo事件类来传递参数。

移除事件

		// 移除无参事件
        public void RemoveEventListener(string eventName, UnityAction action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
            	// 如果存在对应的事件则移除对应的回调action
                (_eventDic[eventName] as EventInfo).Actions -= action;
            }
        }

		// 移除有参事件
        public void RemoveEventListener<T>(string eventName, UnityAction<T> action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions -= action;
            }
        }

事件接口,类

这里的事件设置了两种事件类型,带参数和不带参数的事件。所以为了方便都让它们实现了同一个事件接口,方便事件中心来管理。

事件接口

    public interface IEventInfo
    {
    	// 空的接口,方便管理用
    }

无参数事件类

    public class EventInfo : IEventInfo
    {	
    	// 使用Unity定义的无参委托
        public UnityAction Actions;
		
		// 创建实例时需要传入对应的委托
        public EventInfo(UnityAction action)
        {
        	// 委托之间组合,形成新的委托
            Actions += action;
        }
    }

带参数事件类

    public class EventInfo<T> : IEventInfo
    {
        public UnityAction<T> Actions;

        // 泛型类构造函数不需要带尖括号<>
        public EventInfo(UnityAction<T> action)
        {
            Actions += action;
        }
    }

事件名类

添加一个静态类,专门管理事件对应的名称,具体如下代码所示:

namespace Managers
{
    // 在这个类中添加事件名称
    public static class MyEventConst
    {
        public const string PlayerAttackOver = "PlayerAttackOver";

        public const string PlayerXInput = "PlayerXInput";

        public const string PlayerKeyDownInput = "PlayerKeyDownInput";
    }
}

完整代码参考

using System.Collections.Generic;
using UnityEngine.Events;

namespace Managers
{
    public class MyEventManager
    {
        private static MyEventManager _instance;

        // public static MyEventManager Instance
        // {
        //     get { return instance ??= new MyEventManager(); }
        // }

        public static MyEventManager Instance => _instance ??= new MyEventManager();

        private readonly Dictionary<string, IEventInfo> _eventDic;

        private MyEventManager()
        {
            _eventDic = new Dictionary<string, IEventInfo>();
        }

        // 添加事件监听
        public void AddEventListener(string eventName, UnityAction action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo).Actions += action;
            }
            else
            {
                _eventDic.Add(eventName, new EventInfo(action));
            }
        }

        // 删除事件监听
        public void RemoveEventListener(string eventName, UnityAction action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo).Actions -= action;
            }
        }

        // 事件触发器
        public void EventTrigger(string eventName)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo).Actions?.Invoke();
            }
        }

        public void AddEventListener<T>(string eventName, UnityAction<T> action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions += action;
            }
            else
            {
                _eventDic.Add(eventName, new EventInfo<T>(action));
            }
        }

        public void RemoveEventListener<T>(string eventName, UnityAction<T> action)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions -= action;
            }
        }

        public void EventTrigger<T>(string eventName, T info)
        {
            if (_eventDic.ContainsKey(eventName))
            {
                (_eventDic[eventName] as EventInfo<T>).Actions?.Invoke(info);
            }
        }

        // 清除所有事件
        public void ClearAllEvent()
        {
            _eventDic.Clear();
        }
    }

    public interface IEventInfo
    {
    }

    public class EventInfo : IEventInfo
    {
        public UnityAction Actions;

        public EventInfo(UnityAction action)
        {
            Actions += action;
        }
    }

    public class EventInfo<T> : IEventInfo
    {
        public UnityAction<T> Actions;

        // 泛型类构造函数不需要带尖括号<>
        public EventInfo(UnityAction<T> action)
        {
            Actions += action;
        }
    }
}

使用参考

比如我需要在玩家脚本中监听玩家攻击结束事件,为此添加事件。
无参数

        private void BindEvent()
        {
        	// 为事件PlayerAttackOver添加回调PlayerAttackOverCallback
            MyEventManager.Instance.AddEventListener(MyEventConst.PlayerAttackOver, PlayerAttackOverCallback);
        }

        private void RemoveEvent()
        {
            MyEventManager.Instance.RemoveEventListener(MyEventConst.PlayerAttackOver, PlayerAttackOverCallback);
        }

		// PlayerAttackOver事件触发后需要执行的函数
        private void PlayerAttackOverCallback()
        {
            _curComboCounter = ++_curComboCounter % _totalCombo;
            Fsm.SwitchState(StateType.Idle);
        }

带参数

        private void BindEvent()
        {
            MyEventManager.Instance.AddEventListener<KeyCode>(MyEventConst.PlayerKeyDownInput, ChangeToOtherState);
        }

        private void RemoveEvent()
        {
            MyEventManager.Instance.RemoveEventListener<KeyCode>(MyEventConst.PlayerKeyDownInput, ChangeToOtherState);
        }

        private void ChangeToOtherState(KeyCode keyCode)
        {
            switch (keyCode)
            {
                case KeyCode.LeftShift:
                    Fsm.SwitchState(StateType.Dash);
                    break;
                case KeyCode.Mouse0:
                    Fsm.SwitchState(StateType.Attack);
                    break;
                default:
                    break;
            }
        }

触发事件
无参数

        private void AttackOverTrigger()
        {
        	// 玩家攻击结束时触发事件PlayerAttackOver
			MyEventManager.Instance.EventTrigger(MyEventConst.PlayerAttackOver);
        }

带参数

MyEventManager.Instance.EventTrigger(MyEventConst.PlayerKeyDownInput, _curKeyCode);

总结

把事件管理器的一种实现方法,保存在这里防止以后忘记了。

Unity SteamVR 是一个基于Unity引擎的虚拟现实(VR)开发工具,它提供了一套丰富的API用于处理VR应用程序中的事件。 SteamVR 事件是基于输入设备(例如:触摸控制器)在VR应用程序中发生的用户交互事件。这些事件可以包括按键按下、按键释放、手柄触发、手柄抬起等等。通过监听这些事件,开发者可以在应用程序中实现丰富的用户交互功能。 在Unity中使用SteamVR进行事件处理非常简单。首先,我们需要引入SteamVR插件并将其添加到我们的项目中。然后,我们可以编写代码来监听事件并处理它们。 在Unity中,我们可以使用SteamVR提供的API来获取输入设备的状态并注册事件监听器。例如,我们可以使用`SteamVR_Input`中的`GetState`方法来获取手柄按键的状态,然后根据按键状态执行相应的操作。 另外,我们还可以使用`SteamVR_ActionSet`和`SteamVR_Action`来处理事件。`SteamVR_ActionSet`是一个逻辑组,用于管理一组相关事件,而`SteamVR_Action`则代表一个具体的事件。我们可以在`SteamVR_Action`中注册事件处理函数,使得当相关事件发生时,相应的处理函数会被调用。 最后,在事件处理函数中,我们可以编写代码来响应事件触发。例如,在按下某个按键时,我们可以移动角色、切换场景、播放音效等等。 总而言之,Unity SteamVR 提供了丰富的事件处理功能,让我们可以轻松地处理VR应用程序中发生的用户交互事件。通过监听事件,我们可以为用户提供更加沉浸式和交互式的虚拟现实体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值