简体   繁体   English

我无法修改 ScriptableObject 值。 [Unity3D]

[英]I can't modify ScriptableObject value. [Unity3D]

So, I have a ScriptableObject which stores the KeyCodes for the player input:所以,我有一个 ScriptableObject 存储玩家输入的 KeyCode:

InputController.cs:输入控制器.cs:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 [CreateAssetMenu(fileName = "InputController", menuName = "ScriptableObjects/InputController", order = 1)]
 
 public class InputController : ScriptableObject
 {
     public KeyCode jump;
     public KeyCode left;
     public KeyCode right;
     public KeyCode shoot;
     public KeyCode hover;
     public KeyCode dash;
 }

The initial key values are assigned from the inspector, but I want to be able to change them from the options menu during runtime, so I created coroutine in another file, and that coroutine is called inside a function, which itself is assigned to a button.初始键值是从检查器分配的,但我希望能够在运行时从选项菜单中更改它们,所以我在另一个文件中创建了协程,并且该协程在 function 中调用,它本身被分配给一个按钮.

The coroutine waits for me to press a key, and is supposed to assign that key to the corresponding action, in this case, jumping:协程等待我按下一个键,并且应该将该键分配给相应的动作,在这种情况下,跳跃:

UI.cs: UI.cs:

public List<InputController> warshControls = new List<InputController>(); //This list stores the two ScritableObjects containing the control keys for the two players, assigned in the inspector.

     IEnumerator changeKey(KeyCode key)
     {   
     bool waitforInput=true;
     pressKeyText.text="Press a Key!";
     while(waitforInput)
     {
     foreach(KeyCode vKey in System.Enum.GetValues(typeof(KeyCode))){
             if(Input.GetKey(vKey)){
                 key=vKey;
                 waitforInput=false;
                 pressKeyText.text=" ";
                 Debug.Log(key);
                 Debug.Log(warshControls[0].jump);
             }
         }  
         yield return null;  
     }
 }
 
 public void setPlayer1Jump()
 {
     StartCoroutine("changeKey", warshControls[0].jump);
 }
 //This is the function assigned to the button, it calls the coroutine to change the jumping key for Player1.

According to the Debug Logs, the value of the parameter "key" does change to whatever key I pressed, but for some reason the value of the argument I passed stays the same, meaning if the value of "warshControls[0].jump" was the key Z by default, and I called the coroutine and I pressed the key M , "key" would be M , while "warshControls[0].jump" would stay Z for some reason.根据调试日志,参数“key”的值确实会更改为我按下的任何键,但由于某种原因,我传递的参数的值保持不变,这意味着如果“warshControls[0].jump”的值默认情况下是键Z ,我调用协程并按下键M“键”将是M ,而“warshControls [0].jump”出于某种原因将保持Z

However, if I replace the line "key=vKey;"但是,如果我替换“key=vKey;”with "warshControls[0].jump=vKey;"“warshControls[0].jump=vKey;” , the KeyCode value does actually change (And even persists after Play Mode is turned off which is a different problem entirely), but I want to be able to choose what KeyCode to modify, so I want this problem solved. , KeyCode 值确实发生了变化(甚至在关闭播放模式后仍然存在,这完全是一个不同的问题),但我希望能够选择要修改的 KeyCode,所以我希望解决这个问题。

C# objects are reference type, but they're passed by value. C# 对象是引用类型,但它们是按值传递的。 Passing these objects is like having people do stuff at a house by handing out an address.传递这些物品就像让人们通过分发地址在房子里做事一样。 As long as you are modifying the CONTENTS of the object that was passed, those changes will seen outside the function call.只要您正在修改已通过的 object 的内容,这些更改就会在 function 调用之外看到。

What you do on this line, though不过,你在这条线上做什么

key=vKey;

Is to REPLACE the object you were passed with a new object.是用新的 object 替换您通过的 object。 The key now is NOT the same thing you were given, so the code outside the function doesn't see any changes because it's going to look at the object it gave you, not what you replaced it with.现在的key与您获得的不同,因此 function 之外的代码没有看到任何变化,因为它将查看它给您的 object,而不是您替换它的代码。 The stuff external to the function has no way to know you swapped the objects. function 外部的东西无法知道您交换了对象。

Fortunately you can get around this with the ref keyword, which means you're passing the argument by reference.幸运的是,您可以使用ref关键字解决这个问题,这意味着您通过引用传递参数。 This sounds a lot like the same thing, because objects are reference types, but again they're passed by value by default.这听起来很像同一件事,因为对象是引用类型,但默认情况下它们是按值传递的。

Try the following:尝试以下操作:

IEnumerator changeKey(ref KeyCode key)

and see if that does it for you.看看这是否适合你。 You could also go "up a level" and pass the object holding the jump key, so you're modifying the contents and not the object, but then you'd need a ton of different functions like changeJumpKey, etc. Go the ref route. You could also go "up a level" and pass the object holding the jump key, so you're modifying the contents and not the object, but then you'd need a ton of different functions like changeJumpKey, etc. Go the ref route .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM