Unity3D中无法修改ScriptableObject的KeyCode值问题求助
解决Unity ScriptableObject按键配置运行时修改问题
问题根源
你遇到的核心问题是值类型的传参机制:KeyCode是值类型,当你把warshControls[0].jump作为参数传给协程时,传递的是它的副本。协程里修改key变量只是修改这个副本,根本不会影响原ScriptableObject实例中的属性值。
解决方案
通过传递赋值委托的方式,让协程直接修改目标属性,而不是操作值类型的副本。修改后的代码如下:
修改UI.cs中的协程及调用逻辑
public List<InputController> warshControls = new List<InputController>(); // 已在Inspector赋值 // 修改协程,接收一个用于赋值的委托 IEnumerator ChangeKey(Action<KeyCode> onKeySet) { bool waitForInput = true; pressKeyText.text = "Press a Key!"; while (waitForInput) { foreach (KeyCode vKey in System.Enum.GetValues(typeof(KeyCode))) { // 用GetKeyDown避免按住按键时重复触发 if (Input.GetKeyDown(vKey)) { // 调用委托,直接修改目标属性 onKeySet?.Invoke(vKey); waitForInput = false; pressKeyText.text = " "; Debug.Log($"选中按键: {vKey}"); Debug.Log($"更新后跳跃键: {warshControls[0].jump}"); break; } } yield return null; } } // 玩家1跳跃键设置按钮绑定的函数 public void SetPlayer1Jump() { // 传入赋值逻辑的委托,直接指向warshControls[0].jump属性 StartCoroutine(ChangeKey(newKey => warshControls[0].jump = newKey)); } // 其他按键的设置示例 public void SetPlayer1Left() { StartCoroutine(ChangeKey(newKey => warshControls[0].left = newKey)); } public void SetPlayer2Jump() { StartCoroutine(ChangeKey(newKey => warshControls[1].jump = newKey)); }
原理说明
Action<KeyCode>是引用类型的委托,传递的是赋值逻辑的引用。协程里调用onKeySet(vKey)时,会直接执行你传入的warshControls[0].jump = newKey这类代码,直接修改ScriptableObject实例中的属性,完全绕开了值类型副本的问题。
额外优化建议
- 用
Input.GetKeyDown替代Input.GetKey:避免用户按住按键时,循环内多次触发赋值操作。 - 禁用UI交互:在协程开始时禁用所有设置按钮的交互,防止用户同时触发多个改键流程,结束后再恢复。
- 保存配置:如果需要持久化修改后的按键,可以将ScriptableObject的按键序列化为JSON或存入
PlayerPrefs,游戏启动时加载覆盖初始值。
内容的提问来源于stack exchange,提问作者The Riser
相关产品推荐
相关产品推荐

