Search Unity

Case and Switch with Aiming and Movement

Discussion in 'Scripting' started by RiokuTheSlayer, Sep 2, 2014.

  1. RiokuTheSlayer

    RiokuTheSlayer

    Joined:
    Aug 22, 2013
    Posts:
    356
    Hey all! RiokuTheSlayer here, with yet another probably-gonna-be-unfinished game question!

    I'm just working on this, and I had someone explain the Switch and Case thing(s) and how they work, so but it's not QUITE what I want.

    What's happening is that you hold the button to look left or right(J and L), it moves the camera one "tick" in the direction, then stops, then acts like you're holding it normally. Here's the script, and it does the same vertically (I and K), that's just on the camera because of the way aiming will work.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Controller : MonoBehaviour {
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.  
    10.     }
    11.  
    12.     // Update is called once per frame
    13.     void Update () {
    14.         switch(Input.inputString){
    15.             case "j":
    16.                 transform.Rotate(-Vector3.up*5);
    17.             break;
    18.             case "l":
    19.                 transform.Rotate(Vector3.up*5);
    20.             break;
    21.             case "w":
    22.                 transform.Translate(Vector3.forward/2);
    23.             break;
    24.         }
    25.     }
    26. }
    27.  
    I dunno why it's doing that, and the guy who taught me about the switch and case thing left before I noticed it.
    I ALSO can't hold two keys at once, which I wouldn't mind for movement, but it's annoying to not be able to move and aim
    As you can see, movement is there. It behaves the same, so.

    Thanks in advance!
     
  2. RiokuTheSlayer

    RiokuTheSlayer

    Joined:
    Aug 22, 2013
    Posts:
    356
    Anyone? I'd kinda like to make this, and it'd help if the controls worked well.
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well, quit using Input.inputString. :) That's for typing, and typing has the properties you have observed.

    What you want for controlling a game is just to know what keys are down. Use Input.GetKey for that. (You will probably no longer need switch and case — just use if statements, one for each key you care about.)
     
  4. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Try this:

    Code (CSharp):
    1. void Update()
    2. {
    3.     if (Input.GetKey(KeyCode.J))
    4.         transform.Rotate(-Vector3.up * 5);
    5.  
    6.     else if (Input.GetKey(KeyCode.L))
    7.         transform.Rotate(Vector3.up * 5);
    8.  
    9.     if (Input.GetKey(KeyCode.W))
    10.         transform.Translate(Vector3.forward / 2);
    11. }
    You do not want to use switch in this scenario because the three cases are not mutually exclusive.
    Meaning you want to handle W by itself and you also want to handle W when either J or L is being pressed.

    J and L are mutually exclusive because there would be no sense in processing both because they would cancel each other out. This is why the if... else structure is used for those two.
     
    Last edited: Sep 5, 2014
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    But you don't want to use GetKeyDown, because that returns true only in the frame when the key is first pressed. Use GetKey instead. (And use curly braces around the bodies of your if-blocks; your future self with thank you. :))
     
    GarBenjamin likes this.
  6. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Oh yeah. And also I butchered the L code in my copy & paste edit job. L should be another rotate. Not a translate. Haste makes waste and I have too many APIs in my brain. Another API I use the function KeyDown(KeyCode) returns true if down at this moment otherwise false. GetKey() checks for a key press and returns the ASCII value. Guess that and Unity's merged in my brain when I wrote my original post. ;)

    I have updated my post to use GetKey and to fix the L code.

    Good catch! Thanks!

    Would have confused them even more and my aim here is to get rid of the confusion; not add to it!
     
    Last edited: Sep 5, 2014
  7. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Lol. The curlies aren't necessary unless the block spans multiple statements. Less curlies is cleaner code to read. I used to always use them when I first started in C like 20 years ago. Over time I changed that practice to only use if needed.
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well, we're veering off-topic here, and I know this is somewhat a matter of taste, but over the decades I've gotten more strict about such things, rather than less, and here's why:

    Errors creep into code when the human's reading of it and the computer's reading of it differ. In C-style languages, the compilers don't care about trivial things like whitespace or line breaks, but humans still do; when scanning code, we assume that breaks and indentation accurately reflect the meaning of the code. But sometimes they don't; just yesterday I ran into this gem in a project I'm consulting on:

    Code (csharp):
    1.  if ( !_spentDialogs.Contains( dialogElement ) );
    2.          _spentDialogs.Add( dialogElement );
    Clearly whoever wrote this code intended to add the element only if spentDialogs doesn't already contain it. But our right pinky is trained to smack the semicolon key at the end of almost every line, and in this case, clearly it smacked it even though that wasn't appropriate, and the code silently fails in a subtle way that probably would lead to much head-scratching. The habit of using curly braces here would probably have prevented it. (Not necessarily, I'll admit, but I think probably.)

    Here's another example I've seen from time to time, even more commonly: the original author has only a single statement they need to do conditionally, but it's too long for a one-liner, so they hit return and indent:

    Code (csharp):
    1.  if ( !_spentDialogs.Contains( dialogElement ) )
    2.          _spentDialogs.Add( dialogElement );
    ...then, months later, they or somebody else needs to do something else under the same condition, and they're in a hurry (or come from a Python background!), so they just:

    Code (csharp):
    1.  if ( !_spentDialogs.Contains( dialogElement ) )
    2.          _spentDialogs.Add( dialogElement );
    3.          _elementMap[dialogElement] = ++count;
    ...and again, it compiles fine, but fails in subtle ways that are hard to track down.

    Now I know, you say "well I would never do that!", and you're probably right. An experienced C coder eventually learns to insert the curlies when needed without even thinking about it. But coding standards are there not just for experienced coders, but for the noobs on the team. They make the actual meaning of the code match the appearance of the code. Followed consistently, they reduce the probability of error for everybody.

    So there, that's my rant. Of course everybody can do what they want, and no giant meteor strikes will result, but my recommendation (especially to new coders) is: always use the curly braces around any if statement or loop, unless it's all on one line.

    Cheers,
    - Joe
     
  9. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    P.S. And oh yeah, the opening curly brace should always go at the end of the "if" (or "for" or "while" or whatever) line, not on the line below. The reasoning is much the same as above: if you put it on the next line, then it's easy to accidentally insert a semicolon (or even a statement) on the end of the if-line, which the compiler will love but your users will hate. Get in the habit of always putting the opening curly on the same line, and this error is much harder to commit.

    So, to summarize, this is bad:

    Code (csharp):
    1.   if (something != somethingElse)
    2.       doSomethingCoolWith(something, somethingElse);
    ...and this is also bad:

    Code (csharp):
    1.   if (something != somethingElse)
    2.   {
    3.       doSomethingCoolWith(something, somethingElse);
    4.   }
    ...but this is happy joyfulness:

    Code (csharp):
    1.   if (something != somethingElse) {
    2.       doSomethingCoolWith(something, somethingElse);
    3.   }
     
  10. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Agreed one needs to be careful when updating code.

    Ironically, I have always disliked the formatting of putting the { on the end of the if statement line. I put it on the next line. To me it is more logical with the opening and closing curly lining up and the code block itself being indented. But you are right we are getting off topic and these things are more of a personal preference than anything else. As long as the code is indented and the styles are consistent I am content even when updating code using the curly on the end of the if statement.