You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#:如何在游戏运行时通过脚本重绑定按键?

Unity运行时修改Input Manager按键绑定实现控制菜单

两种实现方案(分Editor/打包后场景)

方案一:Editor环境下直接修改Input Manager配置

如果仅在编辑器内测试或制作工具,可以通过SerializedObject直接修改InputManager.asset的配置,代码示例如下:

using UnityEditor;
using UnityEngine;
using System.Collections;

public class KeyRebindEditorTool : MonoBehaviour
{
    // 目标Input轴名称(需和Input Manager中设置的一致,比如"Jump")
    public string targetAxis = "Jump";

    // 触发按键绑定流程
    public void StartRebind()
    {
        Debug.Log("请按下要绑定的新按键...");
        StartCoroutine(WaitForKeyInput());
    }

    private IEnumerator WaitForKeyInput()
    {
        while (true)
        {
            // 遍历所有按键检测玩家输入
            foreach (KeyCode key in System.Enum.GetValues(typeof(KeyCode)))
            {
                if (Input.GetKeyDown(key))
                {
                    UpdateAxisPositiveKey(targetAxis, key);
                    yield break;
                }
            }
            yield return null;
        }
    }

    private void UpdateAxisPositiveKey(string axisName, KeyCode newKey)
    {
        // 加载InputManager配置文件
        var inputManagerAsset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset")[0];
        var serializedObj = new SerializedObject(inputManagerAsset);
        var axesProp = serializedObj.FindProperty("m_Axes");

        // 遍历找到目标轴并修改正输入键
        for (int i = 0; i < axesProp.arraySize; i++)
        {
            var axisProp = axesProp.GetArrayElementAtIndex(i);
            if (axisProp.FindPropertyRelative("m_Name").stringValue == axisName)
            {
                axisProp.FindPropertyRelative("positiveButton").stringValue = newKey.ToString();
                serializedObj.ApplyModifiedProperties();
                AssetDatabase.SaveAssets();
                Debug.Log($"已将{axisName}的正输入键改为{newKey}");
                break;
            }
        }
    }
}

方案二:打包后游戏的通用解决方案(推荐)

打包后的游戏无法修改InputManager.asset,因此建议自定义输入逻辑,结合PlayerPrefs存储按键映射,确保重启游戏后设置依然有效:

1. 自定义输入管理类

using UnityEngine;
using System.Collections.Generic;

public class CustomInputSystem : MonoBehaviour
{
    // 默认按键配置,与Input Manager中的轴一一对应
    private readonly Dictionary<string, KeyCode> _defaultKeys = new()
    {
        {"Jump", KeyCode.Space},
        {"MoveForward", KeyCode.W},
        {"MoveBackward", KeyCode.S}
    };

    private Dictionary<string, KeyCode> _customKeys;

    void Awake()
    {
        _customKeys = new Dictionary<string, KeyCode>();
        LoadSavedBindings();
    }

    // 加载已保存的按键绑定
    private void LoadSavedBindings()
    {
        foreach (var keyPair in _defaultKeys)
        {
            string saveKey = $"InputBind_{keyPair.Key}";
            if (PlayerPrefs.HasKey(saveKey))
            {
                _customKeys[keyPair.Key] = (KeyCode)PlayerPrefs.GetInt(saveKey);
            }
            else
            {
                _customKeys[keyPair.Key] = keyPair.Value;
            }
        }
    }

    // 对外提供按键按下检测方法
    public bool GetKeyDown(string inputName)
    {
        return _customKeys.TryGetValue(inputName, out var key) && Input.GetKeyDown(key);
    }

    // 对外提供按键按住检测方法
    public bool GetKey(string inputName)
    {
        return _customKeys.TryGetValue(inputName, out var key) && Input.GetKey(key);
    }

    // 保存新的按键绑定
    public void SaveBinding(string inputName, KeyCode newKey)
    {
        if (_customKeys.ContainsKey(inputName))
        {
            _customKeys[inputName] = newKey;
            PlayerPrefs.SetInt($"InputBind_{inputName}", (int)newKey);
            PlayerPrefs.Save();
        }
    }

    // 恢复默认按键配置
    public void RestoreDefaults()
    {
        foreach (var keyPair in _defaultKeys)
        {
            _customKeys[keyPair.Key] = keyPair.Value;
            PlayerPrefs.SetInt($"InputBind_{keyPair.Key}", (int)keyPair.Value);
        }
        PlayerPrefs.Save();
    }
}

2. 控制菜单绑定逻辑示例

在UI菜单脚本中添加如下逻辑,处理按键绑定交互:

using UnityEngine;

public class ControlMenu : MonoBehaviour
{
    public CustomInputSystem inputSystem;
    private bool _isRebinding;
    private string _currentRebindInput;

    // 点击"绑定跳跃键"按钮时调用
    public void StartRebindJump()
    {
        StartRebindProcess("Jump");
    }

    // 点击"绑定前进键"按钮时调用
    public void StartRebindForward()
    {
        StartRebindProcess("MoveForward");
    }

    private void StartRebindProcess(string inputName)
    {
        _currentRebindInput = inputName;
        _isRebinding = true;
        // 此处可更新UI提示,比如显示"请按下新的XX键"
        Debug.Log($"请按下新的{inputName}按键...");
    }

    void Update()
    {
        if (!_isRebinding) return;

        foreach (KeyCode key in System.Enum.GetValues(typeof(KeyCode)))
        {
            if (Input.GetKeyDown(key))
            {
                inputSystem.SaveBinding(_currentRebindInput, key);
                _isRebinding = false;
                // 更新UI显示绑定后的按键
                Debug.Log($"{_currentRebindInput}已绑定到{key}");
                break;
            }
        }
    }

    // 点击"恢复默认"按钮时调用
    public void ResetToDefaults()
    {
        inputSystem.RestoreDefaults();
        // 更新UI显示默认按键
        Debug.Log("已恢复默认按键配置");
    }
}

关键说明

  • 方案一仅适用于Unity Editor环境,打包后会因AssetDatabase属于Editor命名空间报错
  • 方案二更适合正式发布的游戏,兼容性和可靠性更高
  • 以上代码针对旧版Input Manager,若使用Unity新Input System,实现逻辑会有所不同

内容的提问来源于stack exchange,提问作者TheWIzard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 05:03:19