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); });
        }
    }
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM