Unity 按键输入系统(一)

           这段时间制作了游戏内的操作系统,主要制作的原因是,在游戏内很多按键是公用的,但是不同位置的处理逻辑不同,比如在最外层界面上,可以使用ESC打开菜单,但是在二级界面里,使用ESC是返回上个界面,如果要使用判断制作的话,会产生很强的耦合性,要在很多位置加入判断逻辑,所以制作了这套按键,先写出代码,下一篇会介绍怎么使用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class KeystorkeLayer
{
    public string registerName;
    public Dictionary<KeyCode, Util.NoneParamFunction> keystrokeDict = new Dictionary<KeyCode, Util.NoneParamFunction>();
    public Dictionary<int, Util.NoneParamFunction> mouseDict = new Dictionary<int, Util.NoneParamFunction>();
    public Dictionary<string, List<Util.NoneParamFunction>> axisDict = new Dictionary<string, List<Util.NoneParamFunction>>();

    public HashSet<KeyCode> keyDisableHashSet = new HashSet<KeyCode>();
    public HashSet<int> mouseDisableHashSet = new HashSet<int>();
    public HashSet<string> axisDisableHashSet = new HashSet<string>();

    public int axisCheckFrameCount = 1;
    public bool forceTop;

    public KeystorkeLayer(string registerName, bool forceTop)
    {
        this.registerName = registerName;
        this.forceTop = forceTop;
    }

    public void RegisterKeys(List<KeyCode> list, Util.NoneParamFunction callback)
    {
        if (list == null || list.Count <= 0)
        {
            return;
        }
        for (int i = 0; i < list.Count; i++)
        {
            RegisterKey(list[i], callback);
        }
    }

    public void UnRegisterKeys(List<KeyCode> list)
    {
        if (list == null || list.Count <= 0)
        {
            return;
        }
        for (int i = 0; i < list.Count; i++)
        {
            UnRegisterKey(list[i]);
        }
    }

    public void RegisterKey(KeyCode key, Util.NoneParamFunction callback)
    {
        keystrokeDict[key] = callback;
    }

    public void UnRegisterKey(KeyCode key)
    {
        if (!keystrokeDict.ContainsKey(key))
        {
            Debug.LogError("Error Key");
            return;
        }
        keystrokeDict.Remove(key);
    }

    public void SetKeyEnableState(KeyCode key, bool enable)
    {
        if (enable)
        {
            keyDisableHashSet.Remove(key);
        }
        else
        {
            keyDisableHashSet.Add(key);
        }
    }

    public void RegisterMouse(int mouseIndex, Util.NoneParamFunction callback)
    {
        mouseDict[mouseIndex] = callback;
    }

    public void UnRegisterMouse(int mouseIndex)
    {
        if (!mouseDict.ContainsKey(mouseIndex))
        {
            Debug.LogError("Error Mouse");
            return;
        }
        mouseDict.Remove(mouseIndex);
    }

    public void SetMouseEnableState(int mouseIndex, bool enable)
    {
        if (enable)
        {
            mouseDisableHashSet.Remove(mouseIndex);
        }
        else
        {
            mouseDisableHashSet.Add(mouseIndex);
        }
    }

    public void RegisterAixs(string axisName, Util.NoneParamFunction firstCallback, Util.NoneParamFunction secondCallback)
    {
        axisDict[axisName] = new List<Util.NoneParamFunction>();
        axisDict[axisName].Add(firstCallback);
        axisDict[axisName].Add(secondCallback);
    }

    public void UnRegisterAixs(string axisName)
    {
        if(!axisDict.ContainsKey(axisName))
        {
            Debug.LogError("Error Axis");
            return;
        }
        axisDict.Remove(axisName);
    }

    public void SetAxisEnableState(string axisName, bool enable)
    {
        if (enable)
        {
            axisDisableHashSet.Remove(axisName);
        }
        else
        {
            axisDisableHashSet.Add(axisName);
        }
    }


    public void RemoveKeystorkeLayer()
    {
        for (int i = 0; i < QA.keystrokeMan.keystorkeLayerStack.Count; i++)
        {
            if (QA.keystrokeMan.keystorkeLayerStack.ElementAt(i) == this)
            {
                Stack<KeystorkeLayer> tempStack = new Stack<KeystorkeLayer>();
                for (int j = 0; j < i; j++)
                {
                    tempStack.Push(QA.keystrokeMan.keystorkeLayerStack.Pop());
                }
                QA.keystrokeMan.keystorkeLayerStack.Pop();
                while (tempStack.Count > 0)
                {
                    QA.keystrokeMan.keystorkeLayerStack.Push(tempStack.Pop());
                }
            }
        }
        // 从Stack中删除层时,也从exitLayerStack中删除
        if (QA.keystrokeMan.exitLayerStack.Contains(this))
        {
            for (int i = 0; i < QA.keystrokeMan.exitLayerStack.Count; i++)
            {
                if (QA.keystrokeMan.exitLayerStack.ElementAt(i) == this)
                {
                    Stack<KeystorkeLayer> tempStack = new Stack<KeystorkeLayer>();
                    for (int j = 0; j < i; j++)
                    {
                        tempStack.Push(QA.keystrokeMan.exitLayerStack.Pop());
                    }
                    QA.keystrokeMan.exitLayerStack.Pop();
                    while (tempStack.Count > 0)
                    {
                        QA.keystrokeMan.exitLayerStack.Push(tempStack.Pop());
                    }
                }
            }
        }
        Debug.LogError("PopTopKeystorkeLayer......." + registerName);
    }
}

public class KeystrokeManager
{
    public Stack<KeystorkeLayer> keystorkeLayerStack = new Stack<KeystorkeLayer>();
    public Stack<KeystorkeLayer> exitLayerStack = new Stack<KeystorkeLayer>();

    public KeystorkeLayer PushNewKeystorkeLayer(string registerName, bool forceTop = false)
    {
        registerName = registerName.Replace("(Clone)", "");
        Debug.LogError("PushNewKeystorkeLayer......." + registerName);
        KeystorkeLayer layer = new KeystorkeLayer(registerName, forceTop);
        // 检测顶层是否强制置顶
        KeystorkeLayer addLayer = null;
        if (keystorkeLayerStack.Count > 0 && keystorkeLayerStack.Peek().forceTop)
        {
            addLayer = keystorkeLayerStack.Pop();
        }
        keystorkeLayerStack.Push(layer);
        if (addLayer != null)
        {
            keystorkeLayerStack.Push(addLayer);
        }
        return layer;
    }

    public void PopTopKeystorkeLayer()
    {
        if (keystorkeLayerStack.Count <= 0)
        {
            Debug.LogError("No Layer Exist");
            return;
        }
        KeystorkeLayer layer = keystorkeLayerStack.Pop();

        // 从Stack中删除层时,也从exitLayerStack中删除
        if (exitLayerStack.Contains(layer))
        {
            for (int i = 0; i < exitLayerStack.Count; i++)
            {
                if (exitLayerStack.ElementAt(i) == layer)
                {
                    Stack<KeystorkeLayer> tempStack = new Stack<KeystorkeLayer>();
                    for (int j = 0; j < i; j++)
                    {
                        tempStack.Push(exitLayerStack.Pop());
                    }
                    exitLayerStack.Pop();
                    while (tempStack.Count > 0)
                    {
                        exitLayerStack.Push(tempStack.Pop());
                    }
                }
            }
        }

        Debug.LogError("PopTopKeystorkeLayer......." + layer.registerName);
    }

    public void RegisterKeys(List<KeyCode> list, Util.NoneParamFunction callback)
    {
        if (list == null || list.Count <= 0)
        {
            return;
        }
        for (int i = 0; i < list.Count; i++)
        {
            RegisterKey(list[i], callback);
        }
    }

    public void RegisterKey(KeyCode key, Util.NoneParamFunction callback)
    {
        keystorkeLayerStack.Peek().keystrokeDict[key] = callback;
    }

    public void UnRegisterKey(KeyCode key)
    {
        if (!keystorkeLayerStack.Peek().keystrokeDict.ContainsKey(key))
        {
            Debug.LogError("Error Key");
            return;
        }
        keystorkeLayerStack.Peek().keystrokeDict.Remove(key);
    }

    public void SetKeyEnableState(KeyCode key, bool enable)
    {
        if (enable)
        {
            keystorkeLayerStack.Peek().keyDisableHashSet.Remove(key);
        }
        else
        {
            keystorkeLayerStack.Peek().keyDisableHashSet.Add(key);
        }
    }

    public void RegisterMouse(int mouseIndex, Util.NoneParamFunction callback)
    {
        keystorkeLayerStack.Peek().mouseDict[mouseIndex] = callback;
    }

    public void UnRegisterMouse(int mouseIndex)
    {
        if (!keystorkeLayerStack.Peek().mouseDict.ContainsKey(mouseIndex))
        {
            Debug.LogError("Error Mouse");
            return;
        }
        keystorkeLayerStack.Peek().mouseDict.Remove(mouseIndex);
    }

    public void SetMouseEnableState(int mouseIndex, bool enable)
    {
        if (enable)
        {
            keystorkeLayerStack.Peek().mouseDisableHashSet.Remove(mouseIndex);
        }
        else
        {
            keystorkeLayerStack.Peek().mouseDisableHashSet.Add(mouseIndex);
        }
    }

    [System.Obsolete("尽量不要用这个方法,无法通过控制顺序来控制按键时再使用")]
    public void SetKeyEnableState(int index, KeyCode key, bool enable)
    {
        if (index > keystorkeLayerStack.Count - 1 || index < 0)
        {
            Debug.LogError("Error Index");
        }
        var layer = keystorkeLayerStack.ElementAt(index);
        if (enable)
        {
            layer.keyDisableHashSet.Remove(key);
        }
        else
        {
            layer.keyDisableHashSet.Add(key);
        }
    }

    public void CheckInput()
    {
        if (keystorkeLayerStack.Count <= 0)
        {
            return;
        }

        var layer = keystorkeLayerStack.Peek();
        if (Input.anyKeyDown)
        {
            // 键盘
            foreach (var kv in layer.keystrokeDict)
            {
                if (Input.GetKeyDown(kv.Key) && !layer.keyDisableHashSet.Contains(kv.Key))
                {
                    Debug.LogError(layer.registerName + " - " + kv.Key + "!!!!!!!!!!!!!!!!!!!!!!!");
                    kv.Value?.Invoke();
                    return;
                }
            }
        }


        if (Input.GetMouseButtonDown(0) && layer.mouseDict.ContainsKey(0) && !layer.mouseDisableHashSet.Contains(0))
        {
            layer.mouseDict[0]?.Invoke();
            return;
        }

        if (Input.GetMouseButtonDown(1) && layer.mouseDict.ContainsKey(1) && !layer.mouseDisableHashSet.Contains(1))
        {
            layer.mouseDict[1]?.Invoke();
            return;
        }

        // 沒有處理鎖住的問題
        if (Time.frameCount % layer.axisCheckFrameCount == 0)
        {
            // 每五帧执行一次
            foreach (var kv in layer.axisDict)
            {
                float axisValue = Input.GetAxisRaw(kv.Key);
                if (!Mathf.Approximately(axisValue, 0))
                {
                    if (!layer.axisDisableHashSet.Contains(kv.Key))
                    {
                        kv.Value[axisValue > 0 ? 0 : 1]?.Invoke();
                        layer.axisDisableHashSet.Add(kv.Key);
                        return;
                    }
                } else
                {
                    layer.axisDisableHashSet.Remove(kv.Key);
                }
            }
        }

#if UNITY_EDITOR
        if (Input.GetKeyDown(KeyCode.L))
        {
            Debug.Log("Show Layer Info : " + layer.registerName);
            Debug.LogError("=========================");
            foreach (var kv in layer.keystrokeDict)
            {
                Debug.Log(kv.Key + " ---- enable : " + !layer.keyDisableHashSet.Contains(kv.Key));
            }
            foreach (var kv in layer.mouseDict)
            {
                Debug.Log(kv.Key + " ---- enable : " + !layer.mouseDisableHashSet.Contains(kv.Key));
            }
            Debug.Log("=========================");
        }

        if (Input.GetKeyDown(KeyCode.K))
        {
            var s = QA.interfaceUIMan.activePageStack.ToArray();
            for (int i = 0; i < s.Length; i++)
            {
                Debug.Log(s[i].Key);
            }
        }
#endif
    }

}

猜你喜欢

转载自blog.csdn.net/HelloCSDN666/article/details/125388184