为Unity角色控制器自定义横竖轴是否具备可行性?
复刻Unity默认Horizontal/Vertical轴并支持运行时按键重绑定
看起来你已经找对了方向——Unity默认的Input Manager轴确实不支持运行时修改绑定,所以自己实现一套自定义轴系统是最佳方案。下面我会基于你的思路,完善代码并补充关键功能,让它完全复刻默认轴的行为同时支持动态按键重绑定。
完整实现代码
using UnityEngine; using System; public class CustomInputAxis : MonoBehaviour { // 可序列化的按键绑定类,支持Inspector编辑和运行时修改 [Serializable] public class AxisBinding { public KeyCode positiveKey = KeyCode.D; public KeyCode negativeKey = KeyCode.A; public float sensitivity = 1f; public float gravity = 3f; public float deadZone = 0.001f; public float snap = 0f; } [Header("水平轴设置")] public AxisBinding horizontalAxis = new AxisBinding(); [Header("垂直轴设置")] public AxisBinding verticalAxis = new AxisBinding(); // 对应Unity Input.GetAxis的平滑输出值 public float Horizontal { get; private set; } public float Vertical { get; private set; } // 对应Unity Input.GetAxisRaw的原始输出值(无平滑) public float HorizontalRaw { get; private set; } public float VerticalRaw { get; private set; } private void Update() { UpdateAxis(ref Horizontal, ref HorizontalRaw, horizontalAxis); UpdateAxis(ref Vertical, ref VerticalRaw, verticalAxis); } // 核心逻辑:完全复刻Unity默认轴的输入处理流程 private void UpdateAxis(ref float currentValue, ref float rawValue, AxisBinding binding) { // 读取原始按键输入 rawValue = 0f; if (Input.GetKey(binding.positiveKey)) rawValue += 1f; if (Input.GetKey(binding.negativeKey)) rawValue -= 1f; // 应用死区过滤微小误触 if (Mathf.Abs(rawValue) < binding.deadZone) rawValue = 0f; // Snap逻辑:松开按键时立即归0(类似Unity部分轴的行为) if (binding.snap > 0f && rawValue == 0f) { currentValue = 0f; return; } // 计算目标值并应用灵敏度 float targetValue = rawValue * binding.sensitivity; // 应用重力实现平滑过渡(模拟Unity轴的缓动效果) currentValue = Mathf.MoveTowards(currentValue, targetValue, binding.gravity * Time.deltaTime); } // 运行时修改水平轴按键的方法 public void SetHorizontalBinding(KeyCode positiveKey, KeyCode negativeKey) { horizontalAxis.positiveKey = positiveKey; horizontalAxis.negativeKey = negativeKey; } // 运行时修改垂直轴按键的方法 public void SetVerticalBinding(KeyCode positiveKey, KeyCode negativeKey) { verticalAxis.positiveKey = positiveKey; verticalAxis.negativeKey = negativeKey; } // 快速获取移动向量的便捷方法 public Vector2 GetMoveVector() { return new Vector2(Horizontal, Vertical); } }
关键功能说明
- 可自定义的绑定参数:
AxisBinding类复刻了Unity默认轴的所有核心参数(灵敏度、重力、死区等),既可以在Inspector里可视化编辑,也能在运行时动态修改。 - 1:1复刻默认轴行为:
UpdateAxis方法完全模拟Unity Input.GetAxis的处理逻辑,包括平滑过渡、死区过滤、Snap归0等细节,保证你的移动手感和默认轴一致。 - 运行时重绑定支持:通过
SetHorizontalBinding和SetVerticalBinding方法,你可以在任何场景(比如设置界面的按键绑定弹窗)调用这些方法,实时修改玩家的移动按键。
使用示例
在你的移动脚本里直接调用即可:
public class PlayerMovement : MonoBehaviour { public float moveSpeed = 5f; private CustomInputAxis customInput; private void Awake() { customInput = GetComponent<CustomInputAxis>(); } private void Update() { Vector2 moveDir = customInput.GetMoveVector(); transform.Translate(moveDir * moveSpeed * Time.deltaTime, Space.World); } // 比如在设置界面调用这个方法修改按键 public void RebindHorizontalKeys(KeyCode positive, KeyCode negative) { customInput.SetHorizontalBinding(positive, negative); } }
扩展建议
- 如果需要支持手柄输入,可以在
AxisBinding中添加手柄轴字段,结合Input.GetAxis读取手柄摇杆输入; - 可以添加按键绑定的保存/加载功能,用
PlayerPrefs存储用户自定义的按键配置; - 若要支持多输入设备切换,可以扩展成输入映射表,区分键盘、手柄、触摸屏等不同输入源。
内容的提问来源于stack exchange,提问作者Nehiso




