Write a script for character movement
Tutorial
·
Beginner
·
+10XP
·
60 mins
·
(6153)
Unity Technologies

Now that you’ve spent time developing the player character for your game, you’re ready to create a custom script to control its movement.
In this tutorial, you’ll:
- Create a new script Asset in Unity
- Explore the default script that is produced
- Make a vector which can be used to change the character’s position
- Apply vertical and horizontal movement and rotation to your character
- Check that your changes work with Unity’s physics system
When you’ve finished, John Lemon will be ready to creep around a haunted house!
Languages available:
1. The Player Character Continued
In the previous tutorial, you started work on the JohnLemon Prefab, adding a system to animate it and components to make the character work with the physics system. Now you’ll create a custom component: your first script!
What is a script?
A script is a text document containing a series of instructions for the computer. These instructions are commonly called code. The instructions are written in a way that the computer can understand, in this case using a programming language called C# (C Sharp).
C# defines the way the instructions are written and some of the words that are used. Luckily, the words used often have a similar meaning in C# as they do in English. For example, the first word we’ll come across in C# is "using" — this means that the script it is written is using code from somewhere else. Another example is "public", which means that anything can access something. There are too many examples to go through them all here, but in these tutorials you’ll explore each of them as they come up.
All the scripts you will be writing for this project take the form of MonoBehaviours. MonoBehaviours are special types of scripts that can be attached to GameObjects just as components can. This is because they are a specific case of component that you can write yourself.
Scripts share some minor similarities with Prefabs:
- A script is created as an Asset, just like a Prefab is.
- Adding a script to a GameObject as a component is actually instantiating that script, just as adding a Prefab to a scene is instantiating that Prefab.
However, in many respects scripts are very different. Let’s jump straight in and find out more!
2. Create your First Script (PlayerMovement)
First, create your new script as an Asset:
1. Find the Assets > Scripts folder in the Project window. Right-click on the folder and choose Create > C# Script. Name the script "PlayerMovement".
Note: Scripts that are going to be used as a component need to have the same name on the asset as the class name in the script itself. When Unity creates a script file, it gives it a class name which matches what the Asset was first named. However, when the Asset is renamed, the class name does not change.
2. Select your script, and look at the Inspector window. You should see the following code:
Find the line which starts “public class PlayerMovement”. This is what defines the class name. If your script doesn’t say PlayerMovement, delete the script Asset then create a new one named PlayerMovement.
3. Now you have created your script Asset, open it for editing. You can either double click on the Asset, or click the "Open…" button in the Inspector window.
Script editing is not done inside Unity — instead scripts open in another program called Visual Studio. Once that’s opened, you’ll be able to edit the script.
Explore the default script
Let’s break down the default script that you can now see in Visual Studio:
1. The first three lines of code are:
These are called using directives. They allow you to use code implemented elsewhere within this script file. For example, the word "MonoBehaviour" in the next line would not be usable if you didn’t have "using UnityEngine;" here. In most cases, the using directives that are included by Unity by default are enough, so you don’t need to worry about these.
2. The next line is:
This is the start of a class declaration. Classes are like the plans for instances which are called Objects. When a class is instantiated (for example, by attaching a script as a component to a GameObject), that instance is called an object. Objects are the building blocks of code, and they exist throughout the work you’ve already done!
Classes you have already met include Animator, Rigidbody, GameObject, and Transform. These exist in your game already. Another way to think of classes is that they are factory buildings: the factory takes an input, does a few things to it, and then produces an output afterward. We’ll return to this factory analogy with other code elements.
3. The next line is simply an open curly brace/bracket: {
In this series of tutorials, they will be called braces. Braces are an essential part of the C# language, as they define code blocks. Code blocks are lines of code which exist between an open and close brace. Braces must always exist in pairs.
For the class declaration code block, the close brace is at the bottom but there are two more code blocks within the class declaration. The two code blocks contained in the class declaration are indented. Indentation is not technically necessary, but is very helpful in defining where code blocks begin and end.
4. The next line is:
Any text that is preceded by a double forward slash like this is known as a comment. A comment is anything that you want to be completely ignored by the computer. In most cases, they work as a sort of label to explain something about the code around them. In this case, the comment gives a very brief explanation of what is declared below it.
5. After the comment is the start of the first method declaration:
Let’s return to the factory analogy. If a class is a factory, then a method is a machine within that factory. Methods can take in data, perform an operation, and then give out (or return) data.
All method declarations have the same format:
- First they state the return type. This is the type of data that is going to be given out when the method is finished. In this example, the return type is void. This is a special C# word that means nothing — the method returns literally nothing.
- After the return type comes the name of the method, in this case Start.
- After the name there is a pair of open and close curved brace/brackets: (). In this series of tutorials, they will be called parentheses. Within these parentheses, methods have the chance to declare what type of data they want to take in. These pieces of data are called parameters. Since there is nothing between the parentheses, there are no parameters declared.
These three pieces of information (the return type, name and parameters) form a method’s signature. In most cases, a method can have whatever signature you like. However, MonoBehaviour classes can use some special methods which need to have specific signatures. These special methods don’t need to be called from your code, and instead are called at specific times by Unity. Start is one example of a special method. It is called as soon as the GameObject it is on starts, which is usually as soon as the Scene starts. This makes it ideal for doing things like setup that you don’t want to repeat.
6. After the Start method signature is a code block. This defines all the code that is executed whenever the method is called. Calling a method is how you use it — you’ll do this yourself later. To return to the factory analogy: the method declaration is how the machine in the factory works, and calling the method is actually making use of that machine.
A method signature declaration followed by the code block are together known as a method definition. The terms method declaration and method definition are commonly interchanged when talking about C#, because they happen at the same time. The difference only really matters in other languages (such as C++).
7. Now is a good time to talk about the order in which things are written in a class. Keeping with the factory and machines analogy, it doesn’t matter where in your factory the machines are, but the order in which machines perform their operations is very important.
In C# it doesn’t matter in which order methods are declared in a class, but the order in which methods perform their operations matters a lot.
8. The last two parts of the script are another comment and then another method definition.
The Update method is another special method for MonoBehaviours. It is called every frame, before something is rendered to the screen.
Now you have a basic understanding of some of the parts of the default script, let’s customize this script for your game.
3. Create variables for the Horizontal and Vertical axes
Your PlayerMovement script needs to take user input and translate that into character movement.
The first thing you’re going to need to do is get some data from Unity’s input system. The script needs to check what’s happening with the input all the time, and since Update is called every frame it makes perfect sense to check the input there. But what specifically does it need to check?
It makes sense to move the character using the arrow keys or WASD, so the script needs to check the values of those specific keys on the keyboard. It could check whether or not each of those keys are individually either held or not and decide what the character should do (or not), but there’s an alternative that’ll make this a little easier.
Unity has an input manager that defines various buttons and axes which can be found by name. For example, it has an axis called Horizontal, which is represented by the A and D keys and the left and right keys. So by checking that, the player’s computer could decide whether the character should move left or right.
Write the code to create your variables
Let’s get started! Add the following line inside the Update method braces:
It should now look like this:
What does this new line do?
In short, your new line of code is telling the computer, “Create a new float variable and call it horizontal; set that variable equal to the result of this method call.”
If classes are factories and methods are machines in those factories, variables are boxes containing stuff in those factories. In other words, variables are a way of storing data. The data you need to store is the value of the horizontal input axis. In Unity, input axes return a number between -1 and 1 — this type of data is called float. A float represents a number with decimal places.
There are a few pieces of important syntax (structure) in this line of code:
- In C#, an equal sign means assign whatever is on the right (the result of a method) to the variable on the left (a newly created float variable).
- The full stop between Input and GetAxis allows the computer to access something inside the previous object (GetAxis is a method within Input, so to get from Input to GetAxis a full stop is used).
- C# code is made up of things called statements. Each statement can contain one or more instructions to the computer, and can be thought of like sentences. The semicolon marks the end of the statement, and so functions like a full stop does at the end of a sentence.
4. How Did You Create That Variable?
Let’s explore what your code is doing in a little more detail:
You have the class Input, and you are drilling into that to find the method called GetAxis. You are then calling that method by putting parentheses after the name. However, unlike Start and Update, GetAxis has a parameter — that is a piece of data it needs to perform its task. Specifically, GetAxis needs the name of the axis it’s trying to find the value of. You’re trying to find the Horizontal axis value here, so you have given that as a parameter.
The data type for this piece of information is called a string. This refers to a string of characters, for example a word or sentence. By putting speech marks around the word Horizontal, you are instructing the computer that it should be treated like a string.
Once the computer has retrieved the value of the axis it will need to store it somewhere. To the left of method call, you have introduced a new float variable called horizontal and set it equal to the value found from GetAxis.
Next, add another line of code to find the value of the axis called Vertical and store that in a variable called vertical.
The update method should look like this:
You now have the values for both the horizontal and vertical axes. The next step is to combine them into a vector, so that they can be used to change position.
5. Make a Vector
In Unity, 3D space is represented by three coordinates which together made a vector. The data type to represent a vector in Unity is called Vector3. This is what a GameObject’s position is represented by, and so you will need to make a Vector3 representing that change. The movement that the user input represents is fundamental to this class, and you may need to use it for other things too.
With this in mind, it’s important to consider the scope of the variable you need to create.
The scope of a variable is the area of code where it can be used. Usually this is as simple as the code block in which it is declared. For example, both float variables you just declared (horizontal and vertical) are in scope for the whole of the Update method, because that is the code block in which they were declared. They are said to be local to the Update method.
If you want to use a variable in multiple different methods, you can create variables outside of the method’s scope. These are local to the class instead.
Above the method definitions, add the following line:
Your script should now look like this:
The new line of code is instructing the computer to create a Vector3 variable called m_Movement that you can use wherever you want in the PlayerMovement class.
Naming conventions
But what does m_ mean at the beginning of the name? This is part of something called a naming convention. Naming conventions are used to identify a particular object or class of object. In this project, you will be using Unity’s internal naming convention. All variables start with a lowercase letter but subsequent words start with an uppercase letter - this is called camelCase.
The exception to this is non-public member variables, which start with the m_ prefix and all words start with an uppercase letter - this is called PascalCase. Member variables are ones that belong to a class rather than a specific method. The m_ part of the non-public member variables comes from them being 'member' variables.
6. Set the Values for your Variable
Now that you have a variable to store the movement for the character, you need to set the value for it. Since this could change every frame, you need to set it every frame — you should do this in the Update method.
In the Update method, after the horizontal and vertical variables are created, add the following line:
Vectors in 3D space have three values — this Set method assigns a value to each. It has three parameters, one for each coordinate of the vector. The movement vector now has a value of the horizontal input in the x axis, 0 in the y axis and the vertical input in the z axis. There’s also an f after the 0 for the second parameter, which is instructing the computer to treat that number as a float.
Now you need to fix a small problem. The movement vector is made up of two numbers that can have a maximum value of 1. If they both have a value of 1, the length of the vector (known as its magnitude) will be greater than 1. This is the relation between sides of a triangle described by Pythagoras’ theorem.

This means that your character will move faster diagonally than it will along a single axis. In order to make sure this doesn’t happen, you need to ensure the movement vector always has the same magnitude. You can do this by normalizing it. Normalizing a vector means keeping the vector’s direction the same, but changing its magnitude to 1.
Add the following script beneath the previous line you wrote, to call a method on the vector itself:
Your full script should now look like this:
This example includes a gap between getting the input and setting the movement vector. This isn’t important, it’s just to make it appear tidier.
7. Set up the Animator component
Now that you’ve created a movement vector, there are some other jobs that need to be done every frame. You need to instruct the computer to:
- Tell the Animator component whether or not the character is walking
- Get a rotation for the character from player input (similar to the way you got its movement)
- Apply the movement and rotation to the character
Let’s start with the Animator component.
Identify Whether There is Player Input
If there is any player input then your character should be walking, and if there is not then it should be idle.
1. To start off, you need to write a line of code that determines whether or not there is horizontal input. Add the following code after the line normalizing the movement vector:
Here you are creating a bool variable (one that can be either true or false) and calling it hasHorizontalInput. Then you’re setting that equal to the return value of a method. This method is called Approximately and is from the Mathf class. It takes two float parameters and returns a bool — true if the two floats are approximately equal and false otherwise. So in this scenario, the method will return true if the horizontal variable is approximately zero.
But wait! There’s another character in this line you haven’t encountered before: the exclamation mark in front of the method call. This is the logical negation operator and it inverts a bool, setting true to false and false to true. This means that hasHorizontalInput is being set to true when horizontal is not approximately equal to 0. In other words, hasHorizontalInput is true when horizontal is non-zero.
2. It’s not just the horizontal axis you care about, though. Add a similar line for the vertical axis:
This line is doing exactly the same thing, but for the vertical axis.
3. Now that you know when you are getting input on the axes, you need to combine them into a single bool. Add the following line of code:
This line is creating another new bool variable called isWalking, which is set to hasHorizontalInput OR hasVerticalInput. The two vertical lines are the logical or operator. This compares the bool on each side. If either of them or both of them are true then it equates to true, otherwise it equates to false. That means that if hasHorizontalInput or hasVerticalInput are true then isWalking is true, and otherwise it is false.
8. Create a variable to store a reference to the Animator component
Next, you need to tell the Animator component whether or not the character should be walking using the bool you have just created. To do this, you need to access the Animator component.
But hold on — why do you need to do something special to access the Animator component, when you didn’t need to do it to call methods on Input or Mathf? This is due to the methods on Input and Mathf being static.
Static methods are methods which are called on a class’s type, rather than an instance of that class. There is no need to have a single instance of the Input class in order to determine axis values, because input is more of a global concept. As such, the methods which obtain those values have been made static. Likewise, the Mathf class is full of helper methods (methods which help another method perform its task) which don’t involve any specific data for a specific instance of Mathf, and so those methods have also been made static.
However, consider your m_Movement variable. You needed to set values specific to that particular instance of Vector3, so those methods were not static. The important thing to remember is that static methods are called using a type name and non-static methods (or 'instance' methods) are called using an instance name.
9. Get a reference to the Animator component
Before you can access the Animator component you need a reference to it, and this is obtained using a method called GetComponent. This reference will be used throughout the class and not just in a single method; it makes sense to keep it as member variable (like the movement vector) so its scope is local to the class.
At the top of the class, above the movement vector declaration but below the class declaration, add the following line:
The script should now look like this:
Note: In this example the comments above the Start and Update methods have been removed. You can do this too if you like, but you don’t need to — comments don’t affect the code in any way.
10. Set up the reference to the Animator component
You’ve created a variable to store a reference to the Animator component, but so far you haven’t set this variable to anything and it’s empty. When a variable is empty in this way in C#, it is said that its value is null. Whenever there could be a reference to something and there isn’t one, the reference is null.
You don’t want a null reference here, and so now you need to set up the reference properly. You also need to be able to access the Animator component in any method, so it’s important to set the reference as soon as possible.
One of the earliest methods to be called on a MonoBehaviour is the Start method you explored earlier in this tutorial, so it makes perfect sense to set up the reference there. Add the following line to the Start method:
The method should now look like this:
This line of code uses some familiar and some new syntax:
- The variable that you’re assigning to is on the left.
- The name of a method is on the right (but it doesn’t have anything written before it).
- There are angle-shaped brackets around Animator, before the parentheses that you have encountered before.
- The line ends with a semicolon.
What does this reference mean?
Let’s explore your code:
First, why isn’t there a class before GetComponent? When you added that previously, you have were accessing methods on other objects (for example, the Normalize method on the movement vector). However, GetComponent is something that you already have access to: it is part of MonoBehaviour, and so because your class is a MonoBehaviour you have access to it too.
Next, the angle brackets. These have been added because the GetComponent method is generic. A generic method is one that has two different sets of parameters: normal parameters and type parameters. The parameters listed between the angle brackets are the type parameters.
In this scenario, GetComponent needs to know what type of component you looking for. You’re looking for an Animator component, so the type parameter is Animator. The line of code is saying, "Get a reference to a component of type 'Animator', and assign it to the variable called m_Animator."
Set the isWalking Animator Parameter
Now that you have a reference to the Animator component, you can use it to set the IsWalking Animator Parameter that you created in the previous tutorial.
Add the following new line of code below the creation of the isWalking variable in the Update method:
This code is calling the SetBool method using the Animator component reference you just set up. The first parameter is the name of the Animator Parameter that you want to set the value of, and the second is the value you want to set it to. It’s important to get the spelling and capitalisation of the first parameter absolutely correct, otherwise the method won’t know which Animator Parameter to set the value of.
The script should now look like this:
That’s it! You’ve set the value of the Animator Parameter.
11. Create a Rotation for Your Character
Let’s look at the next job that needs to be completed every frame: creating a rotation for your character.
In this game the character should only be able to walk forward, and so needs to face in the same direction as the movement. However, if John Lemon flips quickly to the desired direction it’s going to look really weird, so you need to slow it down a little bit. But just how much should you slow it down?
A slightly easier way to frame that question is considering how fast the character should turn.
To set this speed, you need to create a new variable.
Create a turnSpeed variable
Add the following line to the top of the class, above the Animator member variable:
Let’s explore this code.
You’ve added the word public before the variable declaration. In Unity, public member variables appear in the Inspector window and can therefore be tweaked.
You’ve also used camelCase (rather than PascalCase, with its m_ prefix). This is because the variable is public, and the Unity naming convention uses this format for public member variables. Naming conventions can be very useful, but there’s no technical reason for this.
Calculate your character’s forward vector
Remember: you need the character to face its direction of movement. All Transform components have a forward vector, and so a good intermediary step would be to calculate what you want the character’s forward vector to be.
Add the following line at the bottom of the Update method:
It’s quite a long and complicated-looking line of code, but it includes lots of familiar things. Let’s break it down:
- This code creates a Vector3 variable called desiredForward.
- It sets it to the return of a method called RotateTowards, which is a static method from the Vector3 class. RotateTowards takes four parameters — the first two are Vector3s, and are the vectors that are being rotated from and towards respectively.
- The code starts with transform.forward, and aims for the m_Movement variable. transform.forward is a shortcut to access the Transform component and get its forward vector.
- The next two parameters are the amount of change between the starting vector and the target vector: first the change in angle (in radians) and then the change in magnitude. This code changes the angle by turnSpeed * Time.deltaTime and the magnitude by 0.
Time.deltaTime is the time since the previous frame (you can also think of it as the time between frames). So why do you need to multiplying the turnSpeed by that?
Update is called every frame, and if your game is running at 60 frames per second then that means this method will be called 60 times in a second. There would be a very small change in each call, so that over the 60 frames you get the change you want for a second. But what about a game running at 30 frames per second? Only half of the method calls will have been made in the same time, so only half the turn will have happened. You don’t want the number of frames per second affecting how fast the character turns — that’s not good!
What about if instead of making the change per frame, you were dealing with a change per second? That would make things a lot easier. To do this, you need to multiply whatever change you want per second by the amount of time that a frame took. That’s exactly what this code does.
12. Adjust the turnSpeed variable
The turnSpeed variable is the angle in radians you want the character to turn per second. This is then multiplied by Time.deltaTime to get the amount the character should turn this frame. Radians are a different measurement of angle; they are similar to degrees, but are a more natural measurement. A circle has 2π radians in it, so approximately 6. Your character is always going to take the shortest turn, so the most the character will ever turn is about 3 radians.
Given that, a turnSpeed of 3 would mean it takes about a second for your character to completely turn around. That’s actually quite slow. A turn speed of 6 would mean it takes around half a second to turn around, which is still quite slow. Let’s try a value of 20 and see what that feels like — you can always change this later if you want to.
Change the line declaring the turnSpeed variable at the top of the class to:
Now we have a vector for the direction you want your character to face!
Create and Store a Rotation
Next, you need to use the vector to get a rotation and store it, so that you can use it wherever you want. You’re going to store it like you did the movement vector, so it makes sense to declare its variable there.
Below the line declaring the Vector3 called m_Movement, add the following line:
Quaternions are a way of storing rotations; they get around some of the problems with storing rotations as a 3D vector. This tutorial doesn’t explore them in detail — knowing that they are a way of storing rotations is all you need right now.
You’ve given the Quaternion a default value of Quaternion.identity. Normally, variables that are part of the class (member variables) rather than part of a specific method are set to their default value when an instance of the class is created. For example, a Vector3’s default value is to have x, y and z all set as 0. The same is true for a Quaternion. However, while a zero-vector makes sense (as it is no movement), a zero-quaternion does not make as much sense. Setting this value of Quaternion.identity is simply giving it a value of no rotation, which is a more sensible default.
Now that you have created a rotation variable, you can set it. Below the desiredForward variable creation, add the following line:
This line simply calls the LookRotation method and creates a rotation looking in the direction of the given parameter.
Your script should now look like this:
13. Apply Movement and Rotation to your Character
You’re almost done! The final step is to apply the movement and the rotation to your character. There are many ways you could do this, but since the character needs to be part of the physics system you need to move the Rigidbody instead of using any other technique.
In order to do this, you need a reference to the Rigidbody component. You can get that exactly as you did for the Animator component.
1. Add the following line to your script immediately after the Animator variable declaration:
2. Add another line of code just after setting the reference of the Animator variable:
Now that you have a reference to the Rigidbody, let’s think about the specifics of moving an animated character. The character has a fun Walk animation and it would be good to use the root motion for that. However, the animation doesn’t have any turning in it and if you tried to turn the Rigidbody in the Update method it might get overridden by the animation (which could lead to the character not turning when it should).
What you actually need is some of the root motion of the animation but not all of it — specifically, you need to apply the movement but not the rotation. So how to change how root motion is applied from the Animator? Luckily, MonoBehaviours have a special method you can use to change how root motion is applied from the Animator.
Below the Update method, declare a new method:
This method allows you to apply root motion as you want, which means that movement and rotation can be applied separately.
14. Movement
Let’s start with movement. Add the following line to the new OnAnimatorMove method:
This is another fairly complicated-looking line of code, but again there’s very little that’s completely new to you here.
First, you’re using your reference to the Rigidbody component to call its MovePosition method, and passing in a single parameter: its new position. The new position starts off at the Rigidbody’s current position, and then you’ve add a change to that — the movement vector multiplied by the magnitude of the Animator’s deltaPosition. But what does that mean?
The Animator’s deltaPosition is the change in position due to root motion that would have been applied to this frame. You’re taking the magnitude of that (the length of it) and multiplying by the movement vector which is in the actual direction we want the character to move.
15. Rotation
Next, apply the rotation. Add the following line just below the MovePosition call in the OnAnimatorMove method:
This is very similar to the MovePosition call, except it applies to rotation. This time you’re not applying a change to rotation, you’re just directly setting the rotation.
That is the last line of code in your first script! But there’s one more thing you need to adjust.
16. Change your Update Method
In the previous tutorial, you learned about the Update loop (used for rendering) and the FixedUpdate loop (which runs the physics operations). You’ve made sure that the Animator runs in time with the physics loop to avoid conflict between physics and the animation. However — now you’re overriding the root motion using OnAnimatorMove. This means that OnAnimatorMove is actually going to be called in time with physics, and not with rendering like your Update method.
The movement vector and rotation are set in Update. If OnAnimatorMove gets called first then you will have a problem, because a Quaternion without a value set doesn’t make any sense.
To make sure the movement vector and rotation are set in time with OnAnimatorMove, change your Update method to a FixedUpdate method as follows:
This is another special method that is called automatically by Unity, but this one is in time with physics. Instead of being called before every rendered frame, FixedUpdate is called before the physics system solves any collisions and other interactions that have happened. By default it is called exactly 50 times every second.
That’s it! The completed script should look similar to this:
Remember: in C# the order in which order methods are declared in a class doesn’t matter, so your methods may be arranged slightly differently.
Save your script, and then give yourself a hearty pat on the back! Now it’s time to go back to Unity and test your work.
17. Test your Changes
Add the PlayerMovement Script to JohnLemon
Once you have returned to Unity, you need to add the script to JohnLemon as a component.
You can add script components by clicking the Add Component button in the Inspector window, but you can also do this another way:
1. Select the JohnLemon GameObject.
2. In the Inspector window, click Edit prefab to enter Prefab Mode.
3. In the Project window, go to Assets > Scripts and find the PlayerMovement script.
4. Drag the PlayerMovement script from the Project window to the Inspector window.
5. If your Prefab Mode is not set to Auto Save, click the Save button
6. Click the back arrow to return along the Prefab’s breadcrumb.
7. If the MainScene isn’t loaded, go to the Project window and load it by double clicking on the Scene Asset in the Assets > Scenes folder.
8. Select your JohnLemon GameObject in the Scene — you’ll see that it has all the components and settings you gave to its Prefab.
18. Adjust your Game View Settings
Before you test the Prefab, you may need to adjust some of the settings for Game view. If you have a high resolution monitor, Unity automatically scales the Game window to improve performance. It does this by setting the Scale of the Game window.
Your Scene currently isn’t complicated enough to make performance a concern, so if you have this issue let’s fix it now.
1. Select the Game window tab. You can see if your Game window is scaled at the top.
2. Click on the aspect ratio drop-down which currently says Free Aspect.

3. Disable the Low Resolution Aspect Ratios checkbox and then change the Scale slider to 1x. If you can’t disable this box (or it is already disabled) then don’t worry — this won’t affect the finished game and should be automatically configured for your monitor.
The Game window now looks as it should, so you can test JohnLemon! Click the Play button to begin, and use the arrow keys to move John Lemon around.

Note: If you receive a compiler error message, don’t panic! Go back and check your code against the example carefully; it’s easy to make mistakes, especially when you’ve just written your first script. Make sure to save any fixes and then test in Play Mode again.
19. Summary
In this tutorial you wrote your first script and explored some of the core concepts of coding in Unity. If you have no coding experience and understood everything easily, well done! But don’t worry if you struggled with anything on your first try — it can take some time and practice to feel comfortable these concepts.
In the next tutorial, you’ll be creating the environment and lighting for your game, so that JohnLemon has somewhere spooky to escape from.