unity游戏内动态修改按键

许多单机游戏都带有游戏内按键修改功能,今天就来实现一个。其本质上还是对KeyCode 进一步封装。

配置简单方便如下图:

我将按键分为3种:

1、按下或持续按下会触发。

2、带有值的输入,当按下时会持续增加,松开时会不断减少,值会有一个范围,超出范围将会是边界那个值。

3、类似Horizontal ,Verticale的两个按键控制一个值。

代码如下:

[Serializable]
public class Key
{
    public string name;
    public KeyCode keyCode;
    public KeyCodeType keyType = KeyCodeType.Once;
    [HideInInspector]
    public bool IsDown = false;
    [HideInInspector]
    public bool enable = true;
    
}
public enum KeyCodeType
{
    Once,
    Continuity
}
[Serializable]
public class ValueKey
{
    public string name;
    public Vector2 range=new Vector2(0,1);
    public float currValue=0;
    public float addSpeed = 3f;
    public KeyCode keyCode;
    [HideInInspector]
    public bool enable = true;
}
[Serializable]
public class AxisKey
{
    public string name;
    public float value=0;
    public float addSpeed=5;
    public Vector2 range=new Vector2(-1,1);
    public KeyCode min, max;
    [HideInInspector]
    public bool enable = true;
    public void SetKey(KeyCode a,KeyCode b)
    {
        min = a;
        max = b;
    }
}

 

将按键数据制作成ScriptObject 方便配置

代码如下:

[CreateAssetMenu]
public class InputData : ScriptableObject
{
    public List<Key> keys=new List<Key>() { new Key() };
    public List<ValueKey> valueKeys=new List<ValueKey>() { new ValueKey()};
    public List<AxisKey> axisKeys=new List<AxisKey>() {new AxisKey()};

    public void SetKey(string name,KeyCode key)
    {
        Key key1= GetKey(name);
        if (key1!=null)
        {
            key1.keyCode = key;
        }
    }
    public void SetAxisKey(string name,KeyCode a,KeyCode b)
    {
        AxisKey axisKey = GetAxisKey(name);
        if (axisKey != null)
        {
            axisKey.SetKey(a,b);
        }
    }

    public void SetValueKey(string name,KeyCode key)
    {
        ValueKey valueKey = GetValueKey(name);
        if (valueKey!=null)
        {
            valueKey.keyCode = key;
        }
    }
    public ValueKey GetValueKey(string name)
    {
        int len = valueKeys.Count;
        for (int i = 0; i < len; i++)
        {
            if (valueKeys[i].name==name)
            {
                return valueKeys[i];
            }
        }
        Debug.LogError("ValueKey:" + name + "不存在");
        return null;
    }
    public AxisKey GetAxisKey(string name)
    {
        int len = axisKeys.Count;
        for (int i = 0; i < len; i++)
        {
            if (axisKeys[i].name == name)
            {

                return axisKeys[i];
            }
        }
        Debug.LogError("AxisKey:" + name + "不存在");
        return null;
    }
    public Key GetKey(string name)
    {
        int len = keys.Count;
        for (int i = 0; i < len; i++)
        {
            if (keys[i].name==name)
            {
                return keys[i];
            }
        }
        Debug.LogError("Key:"+name+"不存在");
        return null;
    }
    public float Axis(string name)
    {
        AxisKey axisKey = GetAxisKey(name);
        if (axisKey != null)
        {
            return axisKey.value;
        }
        return 0;
    }
    public bool GetKeyDown(string name)
    {
        Key key = GetKey(name);
        if (key != null)
        {
            return key.IsDown;
        }
        return false;
    }
    public float GetValue(string name)
    {
        ValueKey valueKey = GetValueKey(name);
        if (valueKey != null)
        {
            return valueKey.currValue;
        }
        return 0;
    }
    public void SetKeyEnable(string name,bool enable)
    {
        Key key = GetKey(name);
        if (key!=null)
        {
            key.enable = enable;
            key.IsDown = false;
        }
    }

    public void SetValueKeyEnable(string name,bool enable)
    {
        ValueKey valueKey = GetValueKey(name);
        if (valueKey!=null)
        {
            valueKey.enable = enable;
            valueKey.currValue = 0;
        }
    }
    public void SetAxisKeyEnable(string name,bool enable)
    {
        AxisKey axisKey = GetAxisKey(name);
        if (axisKey!=null)
        {
            axisKey.enable = enable;
            axisKey.value = 0;
        }
    }
    /// <summary>
    /// 每帧更新
    /// </summary>
    public void AcceptInput()
    {
        UpdateKeys();
        UpdateValueKey();
        UpdateAllAxisKey();
    }
    private void UpdateKeys()
    {
        for (int i = 0; i < keys.Count; i++)
        {
            if (keys[i].enable)
            {
                keys[i].IsDown = false;
                switch (keys[i].keyType)
                {
                    case KeyCodeType.Once:
                        if (Input.GetKeyDown(keys[i].keyCode))
                        {
                            keys[i].IsDown = true;
                        }
                        break;
                    case KeyCodeType.Continuity:
                        if (Input.GetKey(keys[i].keyCode))
                        {
                            keys[i].IsDown = true;
                        }
                        break;
                }
            }
        }
    }
    private void UpdateValueKey()
    {
        int len = valueKeys.Count;
        for (int i = 0; i < len; i++)
        {
            if (valueKeys[i].enable)
            {
                if (Input.GetKey(valueKeys[i].keyCode))
                {
                    valueKeys[i].currValue = Mathf.Clamp(valueKeys[i].currValue + valueKeys[i].addSpeed * Time.deltaTime, valueKeys[i].range.x, valueKeys[i].range.y);
                }
                else
                {
                    valueKeys[i].currValue = Mathf.Clamp(valueKeys[i].currValue - valueKeys[i].addSpeed * Time.deltaTime, valueKeys[i].range.x, valueKeys[i].range.y);
                }

            }

        }
    }
    private void UpdateAllAxisKey()
    {
        int len = axisKeys.Count;
        for (int i = 0; i < len; i++)
        {
            UpdateAxisKey(axisKeys[i]);

        }
    }
    private void UpdateAxisKey(AxisKey axisKey)
    {
        if (!axisKey.enable)
            return;
        if (Input.GetKey(axisKey.min) || Input.GetKey(axisKey.max))
        {
            if (Input.GetKey(axisKey.min))
                axisKey.value = Mathf.Clamp(axisKey.value - axisKey.addSpeed * Time.deltaTime, axisKey.range.x, axisKey.range.y);
            if (Input.GetKey(axisKey.max))
                axisKey.value = Mathf.Clamp(axisKey.value + axisKey.addSpeed * Time.deltaTime, axisKey.range.x, axisKey.range.y);
        }
        else if (Input.GetKey(axisKey.min) && Input.GetKey(axisKey.max))
        {
            axisKey.value = 0;
        }
        else
        {
            axisKey.value = Mathf.Lerp(axisKey.value, 0, Time.deltaTime * axisKey.addSpeed);
        }
    }
}

参考Input调用方式,配置类似的调用方式使用起来和原来几乎没什么改变

public class InputManager : MonoBehaviour
{
    public string path= "New Input Data";
    static InputData inputData;
    static  bool activeSetKey = false;
    static  Action<KeyCode> setKey;
    private void Awake()
    {
        inputData = Resources.Load<InputData>(path);
        if (inputData == null)
        {
            throw new Exception("inputData:无法加载");
        }
    }
    public void OnGUI()
    {
        if (!activeSetKey)
            return;
        Event e = Event.current;
        if (e.isKey&&setKey!=null)
        {
            KeyCode key = e.keyCode;
            Debug.Log(key);
            setKey(key);
            setKey = null;
            activeSetKey = false;
        }

    }

    private void Update()
    {
        inputData.AcceptInput();
    }

    public static void StartSetKey(Action<KeyCode> key)
    {
        setKey = key;
        activeSetKey = true;
    }

    public static float GetAxis(string name)
    {
        return inputData.Axis(name);
    }
    public static bool GetKeyDown(string name)
    {
        return inputData.GetKeyDown(name);
    }
    public static float GetValueKey(string name)
    {
        return inputData.GetValue(name);
    }
    public static void SetKey(string name,KeyCode key)
    {
        inputData.SetKey(name,key);
    }
    public static void SetValueKey(string name,KeyCode key)
    {
        inputData.SetValueKey(name,key);
    }
    public static void SetAxisKey(string name,KeyCode a,KeyCode b)
    {
        inputData.SetAxisKey(name,a,b);
    }
}

 使用时候需要修改InputManager的执行顺序,保证输入在其它脚本调用的前方

使用案例包含三种按键和修改按键:

代码如下:

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

public class TestInput : MonoBehaviour
{

    void Update()
    {
        if (InputManager.GetKeyDown("Jump"))
        {
            Debug.Log("Jump");
        }
        if (InputManager.GetKeyDown("Attack"))
        {
            Debug.Log("Attack");
        }
        if (Mathf.Abs(InputManager.GetAxis("Horizontal"))>0.1f)
        {
            Debug.Log("Horizontal:" + InputManager.GetAxis("Horizontal"));
        }
        if (Mathf.Abs(InputManager.GetAxis("Vertical")) > 0.1f)
        {
            Debug.Log("Vertical:" + InputManager.GetAxis("Vertical"));
        }
        if (InputManager.GetValueKey("Space")>0.1f)
        {
            Debug.Log("Space:"+InputManager.GetValueKey("Space"));
        }
        if (Input.GetMouseButtonDown(0))
        {
            InputManager.StartSetKey((keycode)=> { InputManager.SetKey("Jump", keycode); });
        }
    }
}

 

 

posted @ 2021-04-05 15:11  wsfw  阅读(1820)  评论(0编辑  收藏  举报