Search Unity

Noob Question | methods and input

Discussion in 'Scripting' started by Mr_Albert, Jun 13, 2017.

  1. Mr_Albert

    Mr_Albert

    Joined:
    Apr 28, 2017
    Posts:
    25
    hello everybody!

    Sorry for my neophyte questions.

    I would like to create a method that concatenates the "input events" with the "key pressed"... I explain:

    Code (CSharp):
    1.  
    2. //storized input events
    3. var onDown = Input.GetKeyDown;
    4. var onPress = Input.GetKey;
    5. var onUp = Input.GetKeyUp;
    6.  
    7. //storized input type
    8. var keyFORWARD = KeyCode.W;
    9. var keyLEFT = KeyCode.A;
    10. var keyBACKWARD = KeyCode.S;
    11. var keyRIGHT = KeyCode.D;
    12. var keyCROUCH = KeyCode.C;
    13. var keySPACE = KeyCode.Space;
    14. var keySHIFT = KeyCode.LeftShift;
    15.  
    16. var keyStatus = GetKeyStatus("onDown", "keyFORWARD");
    17. Debug.Log("KeyStatus: " + keyStatus);
    18.  

    The method should recreate the complete command line
    Input.GetKeyDown(KeyCode.W)

    Code (CSharp):
    1.  
    2. //get the used key
    3. public GetKeyStatus(string KeyAction, string KeyVal)
    4. {
    5.       string keyStatus = KeyAction+"("+KeyVal+")" ;
    6.       return keyStatus;
    7. }
    8.  
    what am I doing wrong?
    thank you!
     
  2. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    Well, I've never come across this problem but I'll give it a shot.
    First off, Input.GetKey and its variants return a bool if that key was pressed. This means that you can get any other information from this function besides true or false. You can use the method, which will return a string for the current input from the keyboard:
    Code (CSharp):
    1. Input.inputString
    You could then try using Input.GetButton since that uses a string for its argument.

    I don't know if this helps, or answers your question, but I honestly don't know the extent to which what you're trying is possible.
     
    Mr_Albert likes this.
  3. Mr_Albert

    Mr_Albert

    Joined:
    Apr 28, 2017
    Posts:
    25
    I'm not sure I can get what I want
    thank you
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    You can't get what you want with strings. Once your code is compiled, your program doesn't really have a concept of "The function named onDown" - everything is through memory addresses and such.* So you can't tell your program to take a string and find the method with that name, because it doesn't know.

    I would like to point out that there seems to be very little point of doing what you're wanting to do - you're actually increasing the amount of code you need to write to check any given input.

    You can use the first 14 lines of code, and then simply do this, though:
    Code (csharp):
    1. if (onDown(keyFORWARD) ) {
    2. Debug.Log("onDown(keyFORWARD))  was true");
    3. }
    And this would indeed save you a little bit of code.

    * There is an exception known as Reflection, which more or less reverse-looks-up pieces of code by name. But it's slow, it's unreliable, and it doesn't work on many platforms, so don't use it unless you really know what you're doing. It also violates a lot of principles of good data design, so don't use it. In my career I've only found it useful for debug and editor code.
     
    Mr_Albert likes this.
  5. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    drop the storized Input events, you're not even using them

    Code (CSharp):
    1.  
    2.  
    3. //I'd write this in a SerializableDictionary, but thats a different thread
    4. KeyCode keyFORWARD = KeyCode.W;
    5. KeyCode keyLEFT = KeyCode.A;
    6. KeyCode keyBACKWARD = KeyCode.S;
    7. KeyCode keyRIGHT = KeyCode.D;
    8. KeyCode keyCROUCH = KeyCode.C;
    9. KeyCode keySPACE = KeyCode.Space;
    10. KeyCode keySHIFT = KeyCode.LeftShift;
    11.  
    12. public string GetKeyStatus(string inputName, KeyCode code)
    13. {
    14.     return string.Format("Input.{0}({1})",inputName,code);
    15. }
    16.  
    Code (CSharp):
    1. string keyStatus = GetKeyStatus("GetKeyDown", keyFORWARD);
    but he's not checking input... hes just wants to composite a string. I do agree that there seems little point to what he is doing but he never did say what exactly he's using it for.

    and if it is to check for input (even though this is not the way to do it), there is merit to encapsulating the calls.

    "Slow" is relative and really mostly applies to Invoke. even then you can Create a Delegate out of a MethodInfo and the result is a call thats <5% slower than direct calls, which in my book is plenty fast enough. Unity uses Reflection all over the place (especially with UnityEvents) and applies this technique so as not to lose performance. You can check out Jon Skeet's blog about this if you want to know more and see the comparisons.

    Unreliable? I wouldn't ever say that. It does exactly what its designed to do, every time. Complicated, and usually overkill? Sure, those are terms I'd usually use to describe it, but never unreliable. Also Reflection is supported on most platforms, any platform that supports Mono or a C# to C++ transpiler. This includes all Standalones (to as early as 2003), recent iOS and Android, web and all recent consoles. the only platforms I would say give trouble is the Windows Store, Windows Phone 8, and the much older platforms.

    The issue is we're not sure what you want cause you haven't told us.

    we're all going off assumptions. I can make educated guess and if my assumption is correct then yes it is totally possible (and without the need for reflection). so tell us what you're trying to do.
     
    Last edited: Jun 16, 2017
    Mr_Albert and Kiwasi like this.
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Say what? Since when does iOS support reflection?

    When I use a word like "unreliable" for coding, I don't necessarily mean that it will fail randomly. What I mean is that it will be more likely to fail than the alternative, including in how well the technique compensates for human error.

    If you make a typo in compiled code, you'll know it immediately because it'll create a compile-time error. No matter how complicated your project, or how deep into your game the code is where you made the mistake, you can double-click and go right to the error, and just fix it.

    If you make a typo on reflection-dependent code, you won't know until you try to execute that particular bit of code. If your testing methodology isn't bulletproof, it's very possible that a rarely-run piece of code might get all the way to deployment without being noticed.
     
    Mr_Albert likes this.
  7. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    since always it just doesn't support Emit which is rarely needed, if ever. the rest of the Reflection API is fully supported

    What you're talking about is the difference between Syntactic(compile) and Semantic(runtime) errors. which isn't specific to Reflection. you're right in that if your testing isn't good enough then it can break at runtime. but how does that make Reflection the unique case. that can happen to any class.
    Code (CSharp):
    1. //can cause null reference exception! doesn't get caught by the compiler!
    2. transform.GetComponent<Collider>().bounds
     
    Mr_Albert and Kiwasi like this.
  8. Mr_Albert

    Mr_Albert

    Joined:
    Apr 28, 2017
    Posts:
    25
    The idea was to create a method that reconstructs the button event.

    Then something like this:

    If (GetKeyStatus (onPress, A) == true) {
    /do...
    }


    (for now I resolve in other mode... But it would be nice to integrate a method like this in the script)
     
  9. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    wrap it in a struct
    Code (CSharp):
    1. [System.Serializable]public class ActionInput
    2. {
    3.     public enum InputType {OnDown,OnUp,WhileHeld}
    4.     public InputType inputType = InputType.WhileHeld;
    5.     public KeyCode key;
    6.  
    7.     public bool GetInput()
    8.     {
    9.         if(inputType == InputType.OnUp)
    10.             return Input.GetKeyUp(key);
    11.         if(inputType == InputType.OnDown)
    12.             return Input.GetKeyDown(key);
    13.  
    14.         return Input.GetKey(key);
    15.     }
    16. }
    now you can simply call the inputs and they're not bound to specific types of input
    you can even change them at runtime.
    Code (CSharp):
    1.  
    2.  
    3.     public ActionInput goForward;
    4.     public ActionInput goBackward;
    5.  
    6.     private void Update()
    7.     {
    8.         if(goForward.GetInput())
    9.             // do forward stuff
    10.  
    11.         if(goBackward.GetInput())
    12.             // do backward stuff
    13.     }
    14.  
     
    Mr_Albert likes this.
  10. Mr_Albert

    Mr_Albert

    Joined:
    Apr 28, 2017
    Posts:
    25
    wow... simple...
    greate.
    it's not classic "method" (right?) but it's ok...
     
  11. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    Theres more than one way to do this, and they all have their own specific benefits. This has the benefit for being tweakable via the inspector and via code at runtime.

    You could also do it via function delegates.
    Code (CSharp):
    1.  
    2. private Dictionary<string,System.Func<KeyCode,bool>keyMethods;
    3.  
    4. private void Start()
    5. {
    6.     keyMethods = new Dictionary<string,System.Func<KeyCode,bool>
    7.     {
    8.        {"OnDown", Input.GetKeyDown},
    9.        {"OnUp", Input.GetKeyUp},
    10.        {"WhilePressed", Input.GetKey}
    11.     }
    12. }
    13.  
    14. private void Update()
    15. {
    16.     if(keyMethods["OnDown"](KeyCode.Space))
    17.         // space was pressed this frame.
    18. }