zoukankan      html  css  js  c++  java
  • 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); });
            }
        }
    }

  • 相关阅读:
    [面试题]去除字符串中相邻两个字符的重复
    [面试题]单向链表的倒序索引值?
    Android数据存储——文件读写操作(File)
    python操作Excel读写(使用xlrd和xlrt)
    在Ubuntu上安装qq2012客户端
    sharepoint 2010开发webpart(转)

    【Sharepoint 2007】WebPart开发、部署过程全记录(转)
    sharepoint2010最初的了解
    基于windows验证的moss2010站点登录域后还弹出对话框解决方法(转)
  • 原文地址:https://www.cnblogs.com/DazeJiang/p/14618484.html
Copyright © 2011-2022 走看看