8.输入模块

8.输入模块


8.1 知识点

概述

输入模块是游戏开发中一个关键的组成部分,它负责处理玩家输入并触发相应的游戏行为。在本设计中,我们旨在打造一个灵活、可扩展的输入管理系统,以满足不同类型游戏的需求。

设计思路

  1. 接口抽象化: 首先,我们定义了 IBaseInputEvent 接口,用于抽象表示各种输入事件。这个接口定义了输入事件的基本属性和方法,包括获取事件类型、唯一标识符等。

  2. 事件类型枚举: 为了更好地区分不同的输入事件,我们引入了 EBaseInputEventType 枚举类型,用于标识不同的事件类型,如单键按下、长按、抬起事件等。

  3. 抽象基类实现: 接着,我们创建了 BaseAbstractBaseInputEvent 抽象类,作为具体输入事件类的基类。这个抽象类实现了输入事件接口,并提供了通用的方法和属性,如添加、移除监听器等。

  4. 具体事件类实现: 我们根据不同的输入事件类型,实现了具体的事件类,包括单键按下事件、长按事件、组合键按下事件等。每个具体事件类都继承自抽象基类,并根据自身的特点实现了对应的触发条件和执行逻辑。

  5. 输入管理器设计: 我们设计了 BaseInputManager 输入管理器,作为整个输入模块的核心。这个管理器负责统一管理各种输入事件的注册、移除和触发,并处理事件的执行顺序。

  6. 提供简洁接口: 在输入管理器中,我们提供了简洁的接口和方法,供开发者添加、移除输入事件的监听器,并在事件触发时执行相应的方法。这样的设计使得开发者能够更加方便地处理各种输入事件。

实现过程

  1. 定义接口和枚举类型: 首先,我们定义了 IBaseInputEvent 接口和 EBaseInputEventType 枚举类型。

  2. 实现抽象基类: 我们创建了 BaseAbstractBaseInputEvent 抽象类,并在其中实现了输入事件接口的方法和属性。

  3. 实现具体事件类: 根据不同的输入事件类型,我们实现了具体的事件类,如单键按下事件、长按事件等,每个事件类都继承自抽象基类。

  4. 设计输入管理器: 我们设计了 BaseInputManager 输入管理器,并在其中实现了事件的注册、移除和触发逻辑。

  5. 提供简洁接口: 在输入管理器中,我们提供了简洁的接口和方法,如 AddInputEventRemoveInputEvent 等,用于方便地添加、移除输入事件的监听器。

进行测试

我们在 Unity 中创建了一个示例脚本 Lesson08_输入模块,演示了如何使用输入模块来处理各种输入事件。在这个示例中,我们添加了单键按下、长按、组合键按下等事件的监听器,并在事件触发时执行相应的方法。同时,我们还演示了如何在空格键按下时移除所有监听器的示例。

总结

输入模块的设计思路基于灵活性和可扩展性,旨在为游戏开发者提供一个方便、高效的输入管理系统。通过面向接口编程和抽象化设计,我们实现了一个功能强大、易用的输入模块,能够满足不同类型


8.2 知识点代码

BaseInputConst

namespace BaseFramework
{
    /// <summary>
    /// 包含输入模块相关的常量
    /// </summary>
    public static class BaseInputConst
    {
        /// <summary>
        /// 默认的组合按键时间阈值,用于连招等输入事件
        /// </summary>
        public const float defaultComboTimeThreshold = 0.2f;
    }
}

EBaseInputEventType

namespace BaseFramework
{
    /// <summary>
    /// 基础输入事件类型枚举,用于标识不同类型的输入事件
    /// </summary>
    public enum EBaseInputEventType
    {
        /// <summary>
        /// 单个按键按下事件
        /// </summary>
        SingleKeyDown,

        /// <summary>
        /// 单个按键长按事件
        /// </summary>
        SingleKeyHold,

        /// <summary>
        /// 单个按键松开事件
        /// </summary>
        SingleKeyUp,

        /// <summary>
        /// 多个按键长按事件
        /// </summary>
        MultiKeyHold,

        /// <summary>
        /// 多个按键同时按下事件
        /// </summary>
        MultiKeyDown,

        /// <summary>
        /// 组合按键按下事件
        /// </summary>
        ComboKeyDown
    }
}

IBaseInputEvent

using UnityEngine;
using UnityEngine.Events;

namespace BaseFramework
{
    /// <summary>
    /// 输入事件接口,定义了输入事件的基本结构和功能
    /// </summary>
    public interface IBaseInputEvent
    {
        /// <summary>
        /// 输入事件的触发事件,用于添加和移除监听器
        /// </summary>
        UnityEvent InputEvent { get; }

        /// <summary>
        /// 获取输入事件的唯一键,用于识别不同的输入事件
        /// </summary>
        /// <returns>输入事件的唯一键</returns>
        string GetUniqueKey();

        /// <summary>
        /// 获取输入事件的类型
        /// </summary>
        /// <returns>输入事件的类型</returns>
        EBaseInputEventType GetBaseInputEventType();

        /// <summary>
        /// 添加监听器到输入事件
        /// </summary>
        /// <param name="action">要添加的监听器</param>
        void AddListener(UnityAction action);

        /// <summary>
        /// 从输入事件中移除监听器
        /// </summary>
        /// <param name="action">要移除的监听器</param>
        void RemoveListener(UnityAction action);

        /// <summary>
        /// 执行输入事件,触发所有添加的监听器
        /// </summary>
        void ExecuteEvent();
    }
}

BaseAbstractBaseInputEvent

using UnityEngine;
using UnityEngine.Events;

namespace BaseFramework
{
    /// <summary>
    /// 基础抽象输入事件类,实现了IBaseInputEvent接口
    /// </summary>
    public abstract class BaseAbstractBaseInputEvent : IBaseInputEvent
    {
        /// <summary>
        /// 输入事件的UnityEvent,用于添加和移除监听器
        /// </summary>
        public UnityEvent InputEvent { get; } = new UnityEvent();

        /// <summary>
        /// 获取唯一的键,用于标识特定的输入事件
        /// </summary>
        /// <returns>唯一键</returns>
        public abstract string GetUniqueKey();

        /// <summary>
        /// 获取基础输入事件的类型
        /// </summary>
        /// <returns>基础输入事件类型</returns>
        public abstract EBaseInputEventType GetBaseInputEventType();

        /// <summary>
        /// 向输入事件添加监听器
        /// </summary>
        /// <param name="action">要添加的监听器</param>
        public void AddListener(UnityAction action)
        {
            InputEvent.AddListener(action);
        }

        /// <summary>
        /// 从输入事件中移除监听器
        /// </summary>
        /// <param name="action">要移除的监听器</param>
        public void RemoveListener(UnityAction action)
        {
            InputEvent.RemoveListener(action);
        }

        /// <summary>
        /// 执行输入事件的操作
        /// </summary>
        public abstract void ExecuteEvent();
    }
}

BaseSingleKeyDownEvent

using UnityEngine;
using UnityEngine.Events;

namespace BaseFramework
{
    // 单键按下事件类
    public class BaseSingleKeyDownEvent : BaseAbstractBaseInputEvent
    {
        private KeyCode keyCode; // 按键码

        // 构造函数,初始化按键码
        public BaseSingleKeyDownEvent(KeyCode keyCode)
        {
            this.keyCode = keyCode;
        }

        // 获取事件的唯一标识符,这里使用按键码作为唯一标识符
        public override string GetUniqueKey()
        {
            return keyCode.ToString();
        }

        // 获取事件类型,这里是单键按下
        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.SingleKeyDown;
        }

        // 执行事件,检查按键是否按下,如果按下则触发事件
        public override void ExecuteEvent()
        {
            if (Input.GetKeyDown(keyCode))
            {
                InputEvent.Invoke();
            }
        }
    }
}

BaseSingleKeyHoldEvent

using UnityEngine;
using UnityEngine.Events;

namespace BaseFramework
{
    // 单键长按事件类
    public class BaseSingleKeyHoldEvent : BaseAbstractBaseInputEvent
    {
        private KeyCode keyCode; // 按键码
        private float holdTime; // 长按时间
        private bool isNeedKeyUpAgain; // 是否需要再次抬起按键才能触发事件

        private bool isHolding = false; // 是否正在长按
        private float holdTimer = 0f; // 长按计时器

        // 构造函数,初始化按键码、长按时间和是否需要再次抬起按键
        public BaseSingleKeyHoldEvent(KeyCode keyCode, float holdTime, bool isNeedKeyUpAgain = false)
        {
            this.keyCode = keyCode;
            this.holdTime = holdTime;
            this.isNeedKeyUpAgain = isNeedKeyUpAgain;
        }

        // 获取事件的唯一标识符,这里使用按键码、长按时间和是否需要再次抬起按键作为唯一标识符
        public override string GetUniqueKey()
        {
            return keyCode.ToString() + holdTime + isNeedKeyUpAgain;
        }

        // 获取事件类型,这里是单键长按
        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.SingleKeyHold;
        }

        // 执行事件,检查按键是否按下并且长按时间是否达到要求,如果满足则触发事件
        public override void ExecuteEvent()
        {
            if (Input.GetKeyDown(keyCode))
            {
                isHolding = true;
                holdTimer = 0f;
            }

            if (Input.GetKey(keyCode))
            {
                if (isHolding)
                {
                    holdTimer += Time.deltaTime;
                    if (holdTimer >= holdTime)
                    {
                        InputEvent.Invoke();

                        // 需要重新抬起才能再次触发
                        if (isNeedKeyUpAgain)
                        {
                            isHolding = false;
                        }
                        // 不需要重新抬起重置计时器就行
                        else
                        {
                            holdTimer = 0f;
                        }
                    }
                }
            }
            else
            {
                isHolding = false;
            }
        }
    }
}

BaseSingleKeyUpEvent

using UnityEngine;

namespace BaseFramework
{
    // 单键抬起事件类
    public class BaseSingleKeyUpEvent : BaseAbstractBaseInputEvent
    {
        private KeyCode keyCode; // 按键码

        // 构造函数,初始化按键码
        public BaseSingleKeyUpEvent(KeyCode keyCode)
        {
            this.keyCode = keyCode;
        }

        // 获取事件的唯一标识符,这里使用按键码作为唯一标识符
        public override string GetUniqueKey()
        {
            return keyCode.ToString();
        }

        // 获取事件类型,这里是单键抬起
        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.SingleKeyUp;
        }

        // 执行事件,检查按键是否抬起,如果抬起则触发事件
        public override void ExecuteEvent()
        {
            if (Input.GetKeyUp(keyCode))
            {
                InputEvent.Invoke();
            }
        }
    }
}

BaseMultiKeyDownEvent

using System.Collections.Generic;
using UnityEngine;

namespace BaseFramework
{
    // 多键按下事件类
    public class BaseMultiKeyDownEvent : BaseAbstractBaseInputEvent
    {
        private List<KeyCode> keyCodes; // 多个按键码

        private bool eventTriggered = false; // 事件是否已触发的标志

        // 构造函数,初始化多个按键码
        public BaseMultiKeyDownEvent(List<KeyCode> keyCodes)
        {
            this.keyCodes = keyCodes;
        }

        // 获取事件的唯一标识符,这里将按键码排序后拼接成字符串作为唯一标识符
        public override string GetUniqueKey()
        {
            keyCodes.Sort();

            string uniqueKey = "";
            foreach (KeyCode keyCode in keyCodes)
            {
                uniqueKey += keyCode.ToString();
            }

            return uniqueKey;
        }

        // 获取事件类型,这里是多键按下
        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.MultiKeyDown;
        }

        // 执行事件,检查多个按键是否同时按下,如果是则触发事件
        public override void ExecuteEvent()
        {
            // 如果事件已经触发过,要等所有按键都抬起过才能重新触发
            if (eventTriggered)
            {
                bool allKeysUp = true;
                for (int i = 0; i < keyCodes.Count; i++)
                {
                    // 检查当前按键有没有抬起
                    if (Input.GetKey(keyCodes[i]) || Input.GetKeyDown(keyCodes[i]))
                    {
                        allKeysUp = false;
                    }
                }

                if (allKeysUp)
                {
                    eventTriggered = false;
                }
                else
                {
                    return;
                }
            }

            // 检查多个按键是否同时按下
            bool allKeysPressed = true;
            foreach (KeyCode keyCode in keyCodes)
            {
                if (!Input.GetKey(keyCode) && !Input.GetKeyDown(keyCode))
                {
                    allKeysPressed = false;
                    break;
                }
            }

            // 如果多个按键同时按下,则触发事件
            if (allKeysPressed)
            {
                InputEvent.Invoke();

                eventTriggered = true;
            }
        }
    }
}

BaseMultiKeyHoldEvent

using System.Collections.Generic;
using UnityEngine;

namespace BaseFramework
{
    // 多键长按事件类
    public class BaseMultiKeyHoldEvent : BaseAbstractBaseInputEvent
    {
        private List<KeyCode> keyCodes; // 多个按键码
        private float holdTime; // 长按时间
        private bool[] isHolding; // 是否正在长按
        private float[] holdTimers; // 长按计时器
        private bool eventTriggered = false; // 事件是否已触发的标志

        private bool isNeedKeyUpAgain = true;

        public BaseMultiKeyHoldEvent(List<KeyCode> keyCodes, float holdTime,bool isNeedKeyUpAgain = true)
        {
            this.keyCodes = keyCodes;
            this.holdTime = holdTime;
            this.isNeedKeyUpAgain = isNeedKeyUpAgain;
            isHolding = new bool[keyCodes.Count];
            holdTimers = new float[keyCodes.Count];
        }

        public override string GetUniqueKey()
        {
            keyCodes.Sort();

            string uniqueKey = "";
            foreach (KeyCode keyCode in keyCodes)
            {
                uniqueKey += keyCode.ToString();
            }

            uniqueKey += holdTime;
            uniqueKey += isNeedKeyUpAgain;
            return uniqueKey;
        }

        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.MultiKeyHold;
        }

        public override void ExecuteEvent()
        {
            // 如果事件已经触发过,要等三个键都抬起过才能重新触发
            if (eventTriggered)
            {
                bool allKeysUp = true;
                for (int i = 0; i < keyCodes.Count; i++)
                {
                    // 检查当前按键有没有抬起
                    if (Input.GetKey(keyCodes[i]) || Input.GetKeyDown(keyCodes[i]))
                    {
                        allKeysUp = false;
                    }
                }

                if (allKeysUp)
                {
                    eventTriggered = false;
                }
                else
                {
                    return;
                }
            }


            // 标记是否所有按键都被按下
            bool allKeysPressed = true;

            // 遍历所有按键
            for (int i = 0; i < keyCodes.Count; i++)
            {
                // 检查当前按键是否没有被按下
                if (!Input.GetKey(keyCodes[i]))
                {
                    // 如果有按键没有被按下,则不满足所有按键被按下的条件
                    allKeysPressed = false;

                    // 标记当前按键不再被长按
                    isHolding[i] = false;

                    // 重置当前按键的长按计时器
                    holdTimers[i] = 0f;
                }
                // 如果当前按键被按下并且之前未被标记为正在长按
                else if (!isHolding[i])
                {
                    // 标记当前按键为正在长按
                    isHolding[i] = true;

                    // 重置当前按键的长按计时器
                    holdTimers[i] = 0f;
                }

                // 如果当前按键正在长按
                if (isHolding[i])
                {
                    // 增加当前按键的长按时间
                    holdTimers[i] += Time.deltaTime;

                    // 如果当前按键的长按时间未达到设定的长按时间
                    if (holdTimers[i] < holdTime)
                    {
                        // 不满足所有按键被按下的条件
                        allKeysPressed = false;
                    }
                }
            }

            // 如果所有按键都被按下
            if (allKeysPressed)
            {
                // 触发输入事件
                InputEvent.Invoke();

                if (isNeedKeyUpAgain)
                {
                    // 标记事件已经触发过 要抬起才能重新触发
                    eventTriggered = true;
                }


                // 重置所有长按计时器和标志位,以便重新检查是否满足触发条件
                ResetHoldTimersAndFlags();
            }
        }

        // 重置所有长按计时器和标志位
        private void ResetHoldTimersAndFlags()
        {
            for (int i = 0; i < keyCodes.Count; i++)
            {
                isHolding[i] = false;
                holdTimers[i] = 0f;
            }
        }
    }
}

BaseComboKeyDownEvent

using System.Collections.Generic;
using UnityEngine;

namespace BaseFramework
{
    // 组合键按下事件类
    public class BaseComboKeyDownEvent : BaseAbstractBaseInputEvent
    {
        private List<KeyCode> keyCodes; // 组合按键码
        private float comboTimeThreshold = BaseInputConst.defaultComboTimeThreshold; // 组合键时间阈值
        private Dictionary<KeyCode, float> keyPressTimes; // 记录按键按下的时间

        private bool eventTriggered = false; // 事件是否已触发的标志

        // 构造函数,初始化组合按键码和组合键时间阈值
        public BaseComboKeyDownEvent(List<KeyCode> keyCodes,
            float comboTimeThreshold = BaseInputConst.defaultComboTimeThreshold)
        {
            this.keyCodes = keyCodes;
            this.comboTimeThreshold = comboTimeThreshold;
            keyPressTimes = new Dictionary<KeyCode, float>();
        }

        // 获取事件的唯一标识符,这里将组合按键码排序后拼接成字符串,并加上组合键时间阈值作为唯一标识符
        public override string GetUniqueKey()
        {
            string uniqueKey = "";
            foreach (KeyCode keyCode in keyCodes)
            {
                uniqueKey += keyCode.ToString();
            }

            uniqueKey += comboTimeThreshold;
            return uniqueKey;
        }

        // 获取事件类型,这里是组合键按下
        public override EBaseInputEventType GetBaseInputEventType()
        {
            return EBaseInputEventType.ComboKeyDown;
        }

        // 执行事件,检查组合按键是否同时按下,如果是则触发事件
        public override void ExecuteEvent()
        {
            if (eventTriggered)
            {
                bool allKeysUp = true;
                for (int i = 0; i < keyCodes.Count; i++)
                {
                    // 检查当前按键有没有抬起
                    if (Input.GetKey(keyCodes[i]) || Input.GetKeyDown(keyCodes[i]))
                    {
                        allKeysUp = false;
                    }
                }

                if (allKeysUp)
                {
                    eventTriggered = false;
                }
                else
                {
                    return;
                }
            }

            // 遍历按键列表
            foreach (KeyCode keyCode in keyCodes)
            {
                // 检查是否有按键被按下
                if (Input.GetKeyDown(keyCode))
                {
                    // 记录按键按下的时间
                    keyPressTimes[keyCode] = Time.time;
                }
            }

            // 检查按键按下的顺序和时间间隔
            bool comboPressed = CheckComboPressed();

            // 如果组合按键被按下
            if (comboPressed)
            {
                // 触发输入事件
                InputEvent.Invoke();

                // 清空按键按下时间记录
                keyPressTimes.Clear();

                // 标记事件已经触发过
                eventTriggered = true;
            }
        }

        // 检查组合按键是否被按下
        private bool CheckComboPressed()
        {
            // 获取当前时间
            float currentTime = Time.time;

            // 按照组合按键的顺序检查每个按键的按下时间和时间间隔
            for (int i = 1; i < keyCodes.Count; i++)
            {
                // 获取当前按键和前一个按键的按键码
                KeyCode nowkeyCode = keyCodes[i];
                KeyCode frontkeyCode = keyCodes[i - 1];

                // 检查当前按键和前一个按键是否都记录了按键按下时间
                if (!keyPressTimes.ContainsKey(frontkeyCode) || !keyPressTimes.ContainsKey(nowkeyCode))
                {
                    return false;
                }

                // 计算当前按键和前一个按键的按键按下时间间隔
                float duration = keyPressTimes[nowkeyCode] - keyPressTimes[frontkeyCode];

                // 如果按键按下的时间间隔在组合键时间阈值内,继续检查下一个按键
                if (duration >= 0 && duration <= comboTimeThreshold)
                {
                    continue;
                }
                // 如果按键按下的时间间隔超出了组合键时间阈值,返回 false
                else
                {
                    return false;
                }
            }

            // 如果所有按键的按键按下时间间隔都在组合键时间阈值内,返回 true
            return true;
        }
    }
}

BaseInputManager

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

namespace BaseFramework
{
    public class BaseInputManager : BaseSingletonInCSharp<BaseInputManager>
    {
        private bool isCheckInput = false;

        private Dictionary<EBaseInputEventType, Dictionary<string, IBaseInputEvent>> inputEventDictionarys =
            new Dictionary<EBaseInputEventType, Dictionary<string, IBaseInputEvent>>();

        private Dictionary<EBaseInputEventType, Dictionary<string, UnityAction>> inputEventToRemoveDictionarys =
            new Dictionary<EBaseInputEventType, Dictionary<string, UnityAction>>();


        public BaseInputManager()
        {
            BaseMonoBehaviourManager.Instance.onUpdate.AddListener(OnUpdateCheckInput);
        }

        public void SetCheckInput(bool isCheckInput)
        {
            this.isCheckInput = isCheckInput;
        }

        private void OnUpdateCheckInput()
        {
            if (!isCheckInput)
                return;

            UpdateCheckInputEvents();
        }

        private void UpdateCheckInputEvents()
        {
            foreach (KeyValuePair<EBaseInputEventType, Dictionary<string, IBaseInputEvent>> dic in
                     inputEventDictionarys)
            {
                foreach (KeyValuePair<string, IBaseInputEvent> item in dic.Value)
                {
                    item.Value.ExecuteEvent();
                }
            }

            foreach (KeyValuePair<EBaseInputEventType, Dictionary<string, UnityAction>> dic in
                     inputEventToRemoveDictionarys)
            {
                foreach (KeyValuePair<string, UnityAction> item in dic.Value)
                {
                    if (!inputEventDictionarys.ContainsKey(dic.Key)) return;

                    if (inputEventDictionarys[dic.Key].ContainsKey(item.Key))
                    {
                        inputEventDictionarys[dic.Key][item.Key].RemoveListener(item.Value);
                    }
                }

                dic.Value.Clear();
            }
        }

        #region AddInputEvent

        public void AddInputEvent(IBaseInputEvent inputEvent, UnityAction action)
        {
            if (!inputEventDictionarys.ContainsKey(inputEvent.GetBaseInputEventType()))
            {
                inputEventDictionarys[inputEvent.GetBaseInputEventType()] =
                    new Dictionary<string, IBaseInputEvent>();
            }

            Dictionary<string, IBaseInputEvent> nowInputEventTypeDic =
                inputEventDictionarys[inputEvent.GetBaseInputEventType()];

            if (!nowInputEventTypeDic.ContainsKey(inputEvent.GetUniqueKey()))
            {
                nowInputEventTypeDic.Add(inputEvent.GetUniqueKey(), inputEvent);
            }

            nowInputEventTypeDic[inputEvent.GetUniqueKey()].AddListener(action);
        }


        public void AddSingleKeyDownInputEvent(KeyCode keyCode, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyDownEvent(keyCode);

            AddInputEvent(inputEvent, action);
        }

        public void AddSingleKeyHoldInputEvent(KeyCode keyCode, float holdTime, UnityAction action,
            bool isNeedKeyUpAgain = true)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyHoldEvent(keyCode, holdTime, isNeedKeyUpAgain);

            AddInputEvent(inputEvent, action);
        }

        public void AddSingleKeyUpInputEvent(KeyCode keyCode, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyUpEvent(keyCode);

            AddInputEvent(inputEvent, action);
        }

        public void AddMultiKeyHoldInputEvent(List<KeyCode> keyCodes, float holdTime, UnityAction action,
            bool isNeedKeyUpAgain = true)
        {
            IBaseInputEvent inputEvent = new BaseMultiKeyHoldEvent(keyCodes, holdTime, isNeedKeyUpAgain);

            AddInputEvent(inputEvent, action);
        }

        public void AddMultiKeyDownInputEvent(List<KeyCode> keyCodes, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseMultiKeyDownEvent(keyCodes);

            AddInputEvent(inputEvent, action);
        }

        public void AddComboKeyDownInputEvent(List<KeyCode> keyCodes, UnityAction action,
            float comboTimeThreshold = BaseInputConst.defaultComboTimeThreshold)
        {
            IBaseInputEvent inputEvent = new BaseComboKeyDownEvent(keyCodes, comboTimeThreshold);

            AddInputEvent(inputEvent, action);
        }

        #endregion


        #region Remove

        public void RemoveInputEvent(IBaseInputEvent inputEvent, UnityAction action)
        {
            if (!inputEventDictionarys.ContainsKey(inputEvent.GetBaseInputEventType()))
            {
                return;
            }

            Dictionary<string, IBaseInputEvent> nowInputEventTypeDic =
                inputEventDictionarys[inputEvent.GetBaseInputEventType()];

            if (!nowInputEventTypeDic.ContainsKey(inputEvent.GetUniqueKey()))
            {
                return;
            }

            // 不直接移除 避免边遍历边移除 而是记录到字典中
            // nowInputEventTypeDic[inputEvent.GetUniqueKey()].RemoveListener(action);

            if (!inputEventToRemoveDictionarys.ContainsKey(inputEvent.GetBaseInputEventType()))
            {
                inputEventToRemoveDictionarys.Add(inputEvent.GetBaseInputEventType(),
                    new Dictionary<string, UnityAction>());
            }

            inputEventToRemoveDictionarys[inputEvent.GetBaseInputEventType()].Add(inputEvent.GetUniqueKey(), action);
        }

        public void RemoveSingleKeyDownInputEvent(KeyCode keyCode, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyDownEvent(keyCode);

            RemoveInputEvent(inputEvent, action);
        }

        public void RemoveSingleKeyHoldInputEvent(KeyCode keyCode, float holdTime, UnityAction action,
            bool isNeedKeyUpAgain = true)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyHoldEvent(keyCode, holdTime, isNeedKeyUpAgain);

            RemoveInputEvent(inputEvent, action);
        }

        public void RemoveSingleKeyUpInputEvent(KeyCode keyCode, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseSingleKeyUpEvent(keyCode);

            RemoveInputEvent(inputEvent, action);
        }

        public void RemoveMultiKeyHoldInputEvent(List<KeyCode> keyCodes, float holdTime, UnityAction action,
            bool isNeedKeyUpAgain = true)
        {
            IBaseInputEvent inputEvent = new BaseMultiKeyHoldEvent(keyCodes, holdTime, isNeedKeyUpAgain);

            RemoveInputEvent(inputEvent, action);
        }

        public void RemoveMultiKeyDownInputEvent(List<KeyCode> keyCodes, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseMultiKeyDownEvent(keyCodes);

            RemoveInputEvent(inputEvent, action);
        }

        public void RemoveComboKeyDownInputEvent(List<KeyCode> keyCodes, UnityAction action)
        {
            IBaseInputEvent inputEvent = new BaseComboKeyDownEvent(keyCodes);

            RemoveInputEvent(inputEvent, action);
        }

        #endregion
    }
}

Lesson08_输入模块

using System.Collections;
using System.Collections.Generic;
using BaseFramework;
using UnityEngine;

public class Lesson08_输入模块 : MonoBehaviour
{
    void Start()
    {
        // 启用输入检测
        BaseInputManager.Instance.SetCheckInput(true);

        // 添加单键按下事件监听器(按下 Q 键时触发 OnKeyQDown 方法)
        BaseInputManager.Instance.AddSingleKeyDownInputEvent(KeyCode.Q, OnKeyQDown);

        // 添加单键长按事件监听器(按下 W 键并长按 2 秒时触发 OnKeyWHold2Seconds 方法)
        BaseInputManager.Instance.AddSingleKeyHoldInputEvent(KeyCode.W, 2, OnKeyWHold2Seconds);

        // 添加单键长按事件监听器,且不需要抬起再次触发(按下鼠标左键并长按 2 秒时触发 OnMouse02Seconds 方法,每 2 秒触发一次)
        BaseInputManager.Instance.AddSingleKeyHoldInputEvent(KeyCode.Mouse0, 2, OnMouse02Seconds, false);

        // 添加多键长按事件监听器(同时按下 E、R、T 键并长按 3 秒时触发 OnKeyERTHold3Seconds 方法)
        BaseInputManager.Instance.AddMultiKeyHoldInputEvent(new List<KeyCode> { KeyCode.E, KeyCode.R, KeyCode.T }, 3,
            OnKeyERTHold3Seconds);

        // 添加多键长按事件监听器,且不需要抬起再次触发(同时按下鼠标右键、F、G 键并长按 3 秒时触发 OnKeyMouse1FGHold3Seconds 方法)
        BaseInputManager.Instance.AddMultiKeyHoldInputEvent(new List<KeyCode> { KeyCode.Mouse1, KeyCode.F, KeyCode.G },
            3, OnKeyMouse1FGHold3Seconds, false);

        // 添加多键按下事件监听器(同时按下 A、S、D 键时触发 OnKeyASDDown 方法)
        BaseInputManager.Instance.AddMultiKeyDownInputEvent(new List<KeyCode> { KeyCode.A, KeyCode.S, KeyCode.D },
            OnKeyASDDown);

        // 添加组合键按下事件监听器(按下 Z、X、C 键组合时触发 OnKeyZXCCombo 方法)
        BaseInputManager.Instance.AddComboKeyDownInputEvent(new List<KeyCode> { KeyCode.Z, KeyCode.X, KeyCode.C },
            OnKeyZXCCombo);

        // 添加单键按下事件监听器(按下空格键时触发 OnSpaceKeyDown 方法)
        BaseInputManager.Instance.AddSingleKeyDownInputEvent(KeyCode.Space, OnSpaceKeyDown);
    }

    // 单键按下事件的处理方法
    void OnKeyQDown()
    {
        Debug.Log("Q键按下");
    }

    // 单键长按事件的处理方法
    void OnKeyWHold2Seconds()
    {
        Debug.Log("W键长按两秒");
    }

    // 鼠标长按事件的处理方法
    void OnMouse02Seconds()
    {
        Debug.Log("鼠标长按2秒,且不用抬起,每2秒触发");
    }

    // 多键长按事件的处理方法
    void OnKeyERTHold3Seconds()
    {
        Debug.Log("ERT键一起长按三秒");
    }

    // 鼠标右键和FG键一起长按事件的处理方法
    void OnKeyMouse1FGHold3Seconds()
    {
        Debug.Log("鼠标右键和FG键一起长按三秒,且不用抬起");
    }

    // 多键按下事件的处理方法
    void OnKeyASDDown()
    {
        Debug.Log("ASD键一起按下");
    }

    // 组合键按下事件的处理方法
    void OnKeyZXCCombo()
    {
        Debug.Log("ZXC键按连招顺序按下");
    }

    // 空格键按下事件的处理方法
    void OnSpaceKeyDown()
    {
        Debug.Log("空格键按下 移除所有监听函数");

        // 移除所有监听函数
        RemoveAllListeners();
    }

    // 移除所有监听函数的方法
    void RemoveAllListeners()
    {
        // 移除单键按下事件的监听器
        BaseInputManager.Instance.RemoveSingleKeyDownInputEvent(KeyCode.Q, OnKeyQDown);

        // 移除单键长按
        BaseInputManager.Instance.RemoveSingleKeyHoldInputEvent(KeyCode.W, 2, OnKeyWHold2Seconds);

        // 移除多键长按事件的监听器
        BaseInputManager.Instance.RemoveMultiKeyHoldInputEvent(new List<KeyCode> { KeyCode.E, KeyCode.R, KeyCode.T }, 3,
            OnKeyERTHold3Seconds);

        // 移除多键按下事件的监听器
        BaseInputManager.Instance.RemoveMultiKeyDownInputEvent(new List<KeyCode> { KeyCode.A, KeyCode.S, KeyCode.D },
            OnKeyASDDown);

        // 移除组合键按下事件的监听器
        BaseInputManager.Instance.RemoveComboKeyDownInputEvent(new List<KeyCode> { KeyCode.Z, KeyCode.X, KeyCode.C },
            OnKeyZXCCombo);

        // 移除单键按下事件的监听器
        BaseInputManager.Instance.RemoveSingleKeyDownInputEvent(KeyCode.Space, OnSpaceKeyDown);
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏