6
\$\begingroup\$

I'm currently learning C# so I can make real games with Unity. This is the first C# program I've built in Unity. Essentially what is does is control the thrust, and rotation of a GameObject shaped like a rocket. It may not necessarily be "real physics" but for my first program, it's good enough.

using UnityEngine;
using System.Collections;

public class RocketController : MonoBehaviour 
{
    public float thrustMultiplier;
    public float rotationSpeed;
    private bool applyThrust = false;

    void Start () { transform.forward = transform.up; }

    // Check for misc keypresses
    void CheckMiscKeys ()
    {
        // Start applying thrust
        if (Input.GetKey (KeyCode.Space))
        {
            applyThrust = true;
        }

        // Stop applying thrust
        if (Input.GetKey (KeyCode.LeftShift))
        {
            applyThrust = false;
        }
    }

    // Check for rotation keypresses
    void CheckRotationKeys ()
    {
        // Rotate forward
        if (Input.GetKey (KeyCode.W))
        {
            transform.Rotate (rotationSpeed * new Vector3 (1, 0, 0));
        }

        // Rotate backwards
        if (Input.GetKey (KeyCode.S))
        {
            transform.Rotate (rotationSpeed * new Vector3 (-1, 0, 0));
        }

        // Rotate left
        if (Input.GetKey (KeyCode.A))
        {
            transform.Rotate (rotationSpeed * new Vector3 (0, -1, 0));
        }

        // Rotate right
        if (Input.GetKey (KeyCode.D))
        {
            transform.Rotate (rotationSpeed * new Vector3 (0, 1, 0));
        }
    }

    // Apply thrust to the rocket's rigidbody
    void ApplyRocketThrust ()
    {
        if (applyThrust)
        {
            Vector3 force = transform.forward * thrustMultiplier;
            rigidbody.AddForce(force);
        }
    }

    // Run physics calculations and misc events
    void FixedUpdate ()
    {
        CheckMiscKeys ();
        CheckRotationKeys ();
        ApplyRocketThrust ();
    }
}

What can be improved? Is there anything I'm doing wrong here?

\$\endgroup\$
6
\$\begingroup\$

UPDATE: Unity has built-in support for rebindable keys. I still urge you to setup rebindable keys, but a better way to do so would be through the system described by https://codereview.stackexchange.com/a/85568/35495.

One thing I really see happening with your code is that some poor gamer using a non-qwerty keyboard (like azerty or dvorak) will have an unplayable game because their keyboard has a different layout. for example, as an azerty-player I use ZQSD instead of WASD, and the W key is on the bottom line. In addition, there are players that use ESDF so they have a larger keyspace available for hotkeys.

The usual way of handling this is:

Make a .cfg or .ini file (basically a text file) in a config folder in your game

Put this code in there:

[Input]
button_W = forward;
button_S = back;
button_A = left;
button_D = right;
//any other buttons you need;

Then you load this into a dictionary when the game loads using a text file parser (plenty of examples for that online).

When the user then does any input, you check which button they pushed. Is it one of the configured buttons? then do the corresponding action. Is it a non-configured button? then return.

You can then use the default Unity launcher to configure these buttons, or you can configure these buttons using a custom config menu ingame.

\$\endgroup\$
  • 1
    \$\begingroup\$ Unity already has an input system with named, remappable buttons using Input.GetButton("forward"), etc. This seems like reinventing the wheel. \$\endgroup\$ – Nick Udell Apr 1 '15 at 8:52
  • \$\begingroup\$ @NickUdell I was completely unaware that this was an existing system in Unity. Thanks for clarifying that. I'll update my question to refer to your answer as well. \$\endgroup\$ – Nzall Apr 1 '15 at 20:14
5
\$\begingroup\$

You should remove code duplication using a dictionary:

void CheckRotationKeys () {
    key_move = {KeyCode.W : (1, 0, 0),
                KeyCode.A : ...
               }

    foreach key in key_move.keys() {
        if (Input.GetKey(key)) {
            transform.Rotate(rotationSpeed * new Vector3(key_move[key]));
        }
    }
}

Please note that this is pseudo-code and you will need some minor syntax modifications to get it to work.

\$\endgroup\$
5
\$\begingroup\$

You should not be using Input.GetKey for controlling your character as it is very difficult to remap to a different control scheme.

Unity has a remappable input system already (go to Project-> Input to have a look yourself). Set up a series of controls you need, and then use either Input.GetAxis(axisName) or Input.GetButton(ButtonName). This allows your players to remap controls at game start, and also allows you to support more complex controls such as mouse and joystick input.

\$\endgroup\$
4
\$\begingroup\$

Vector3 has predefined vectors that you can use in CheckRotationKeys:

back     Shorthand for writing Vector3(0, 0, -1).
down     Shorthand for writing Vector3(0, -1, 0).
forward  Shorthand for writing Vector3(0, 0, 1).
left     Shorthand for writing Vector3(-1, 0, 0).
one      Shorthand for writing Vector3(1, 1, 1).
right    Shorthand for writing Vector3(1, 0, 0).
up       Shorthand for writing Vector3(0, 1, 0).
zero     Shorthand for writing Vector3(0, 0, 0).
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.