PlayerController.cs
Assets > Scripts > PlayerController.cs
Assets > Scripts > PlayerController.cs
using UnityEngine;
using UnityEditor;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5f;
[SerializeField]
private float turnSpeed = 100f;
void Start()
{
Debug.Log("Hello, Number " + AddTwoNumbers(2, 4) + "!");
}
void Update()
{
if (Input.GetKey(KeyCode.W) == true || Input.GetKey(KeyCode.UpArrow) == true) { this.transform.position += this.transform.forward * Time.deltaTime * this.moveSpeed; }
if (Input.GetKey(KeyCode.S) == true || Input.GetKey(KeyCode.DownArrow) == true) { this.transform.position -= this.transform.forward * Time.deltaTime * this.moveSpeed; }
if (Input.GetKey(KeyCode.A) == true || Input.GetKey(KeyCode.LeftArrow) == true) { this.transform.Rotate(this.transform.up, Time.deltaTime * -this.turnSpeed); }
if (Input.GetKey(KeyCode.D) == true || Input.GetKey(KeyCode.RightArrow) == true) { this.transform.Rotate(this.transform.up, Time.deltaTime * this.turnSpeed); }
if (Input.GetKey(KeyCode.E) == true) { this.transform.position += this.transform.right * Time.deltaTime * this.moveSpeed; }
if (Input.GetKey(KeyCode.Q) == true) { this.transform.position -= this.transform.right * Time.deltaTime * this.moveSpeed; }
if (Input.GetKeyDown(KeyCode.Escape) == true)
{
#if UNITY_EDITOR
{
EditorApplication.isPlaying = false;
}
#else
{
Application.Quit();
}
#endif
}
}
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
}
This code will be explained in sections, which each have a different colour to separate them from each other. Comments in the script have been removed from this excerpt, but will be included in the Google Doc containing the script, linked at the bottom of the page.
SECTION 1: Setting up
This section, as the name implies, is mainly just about setting up all the directives and variables for this script to use; basically, giving the script the information and resources to do what's being asked of it.
using UnityEngine
using UnityEditor
The first part is where the directives are called. As put by tutorialspoint (n.d.), "the preprocessor directives give instruction to the compiler to preprocess the information before actual compilation starts." This is essential if you want to do anything in your code.
public class PlayerController : MonoBehaviour
The second part is basically defining your script, that being a container for all of the variables, functions, etc. According to the official Unity3D documentation of MonoBehaviour, version 5.3 (n.d.), "MonoBehaviour is the base class from which every Unity script derives. When you use C#, you must explicitly derive from MonoBehaviour." By default, Unity constructs C# scripts to use the MonoBehaviour class.
[SerializeField]
private float moveSpeed = 5f
[SerializeField]
private float turnSpeed = 100f
The third and final part of this section is the variables. Variables are how you store information such as numerical values, on/off states (referred to as "boolean"), etc. The variables in this context are set as "private floats" meaning they are numerical values (floats) that can be accessed by only the script, and nothing else (private). The "SerializeField" class makes the specific variables visible in Unity's inspector, which is hidden by default when making the variables "private".
SECTION 2: Some random math equation
To be completely blunt here, this section is basically pointless in regards to giving control over the player character to the player. It's more just executing a mathematical equation to show how that would work, and it's only visible in the Unity editor.
void Start()
Firstly, this function creates a Start void. According to a Unity Answers post by tanoshimi (2017), a void is a method where you can call your functions, and it is called a void because the functions within it don't give you a result back that you can use in further calculations (A.K.A. nothing). Because the method is a Start void, all functions within that method will be called as soon as the script is activated.
Debug.Log("Hello, Number " + AddTwoNumbers(2, 4) + "!")
This part in the section is a manually induced debug console log. This is how the math equation can actually be seen—the debug console can be found, by default, at the bottom of the Unity editor. The log opens with a string, which is defined by quotation marks and is just plain text that is put into the log, followed by a custom method that hasn't yet been defined, and then ending with another string.
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2
}
This is the aforementioned custom method that wasn't yet defined. This method is an int (integer) method and contains two integers (in layman's terms, whole numbers) that the method can use for whatever. The ints "number1" and "number2" are whatever integers the call specifies (in the debug log, numbers 2 and 4 were specified). Inside this method, the return function is used, which is the function that outputs a result when the method is called. When the method is called, the two numbers that were specified will be added together and then outputted as a result.
This is the result that is produced in the debug console.
A flow chart that shows the order of operations for each function in this section.
SECTION 3: Making the player model move
This is where all the important stuff happens. The setting up was important, but this is where all the variables that was set up is put into use to make things happen. This section will allow the player controller to be controlled by the player.
void Update()
All of the functions in this section are being called under the Update method, which means the functions will loop every frame starting from when the script is activated.
if (Input.GetKey(KeyCode.W) == true || Input.GetKey(KeyCode.UpArrow) == true) { this.transform.position += this.transform.forward * Time.deltaTime * this.moveSpeed }
if (Input.GetKey(KeyCode.S) == true || Input.GetKey(KeyCode.DownArrow) == true) { this.transform.position -= this.transform.forward * Time.deltaTime * this.moveSpeed }
This is the code that allows the player to move forward and backward. The code checks if the player has held down the key it specifies for that specific frame (that being the W key in this example), and if it finds that the key is being held down, it will utilitze transform.forward to translate the player model's position to move forward. Note that in the function that is bound to the W key, the "+=" operator is used to add transform.position to transform.forward (which increases the value of it, thus moving the player model forward), whereas the function bound to S does the opposite, using the "-=" operator.
A flow chart that shows the order of operations for each function in this section.
if (Input.GetKey(KeyCode.A) == true || Input.GetKey(KeyCode.LeftArrow) == true) { this.transform.Rotate(this.transform.up, Time.deltaTime * -this.turnSpeed) }
if (Input.GetKey(KeyCode.D) == true || Input.GetKey(KeyCode.RightArrow) == true) { this.transform.Rotate(this.transform.up, Time.deltaTime * this.turnSpeed) }
This code fundamentally works the same as the previous code shown, however it uses different functions and does a different thing. This code allows the player to turn the player model to look around. It's a primitive method of looking around, but it's a way of doing so if mouse support is not present. Instead of using transform.position, this function uses the more appropriate transform.Rotate, which is used to rotate objects as the name implies.
A flow chart that shows the order of operations for each function in this section.
if (Input.GetKey(KeyCode.E) == true) { this.transform.position += this.transform.right * Time.deltaTime * this.moveSpeed }
if (Input.GetKey(KeyCode.Q) == true) { this.transform.position -= this.transform.right * Time.deltaTime * this.moveSpeed }
This code was a bit of code that was written by myself. This code introduces strafing, and I did this for the purpose of making movement at least somewhat easier after I realized that trying to move around with forward/backward and turning left/right is VERY clunky. This code goes back to using the former transform.position, but it instead uses transform.right instead of transform.forward to allow the player model to move sideways.
A flow chart that shows the order of operations for each function in this section.
SECTION 4: User convenience
This is the final touches of this script, and is solely to add features that the user would find convenient, such as the ability to exit the game using the Escape key instead of Alt + F4.
if (Input.GetKeyDown(KeyCode.Escape) == true)
{
#if UNITY_EDITOR
{
EditorApplication.isPlaying = false
}
#else
{
Application.Quit()
}
#endif
}
This bit of code allows the user to exit the game when they hit the Escape key, regardless of if they're playing in the Unity Editor or as a standalone build. The code checks if the Escape key has been pressed, and if it has, it then goes onto the sub-parameters.
Because Unity automatically removes the UnityEditor namespace upon building the game, if you try to use the conventional way to exit the Unity Editor's playmode and then build the game, the script will spit out a compiler error and stop the build process. That can be solved by using directives, which is what the "#if UNITY_EDITOR", "#else" and "#endif" lines are. This is called "Conditional Compilation".
If the code finds that the game is being played inside of the Unity Editor, it will use EditorApplication.isPlaying to exit playmode and go back to the Editor. If not, it will use Application.Quit to quit the standalone game to Windows.
A flow chart that shows the order of operations for each function in this section.
The full script
This the full PlayerController.cs script, straight from the project. This version of the script includes the original colouring and also has the original comments that were removed from the code above.