This week we took a pre-made scene with some problems and set out to fix them.

The first two issues were that the plane was flying backwards and at great speed. The initial challenge was to identify what was making the plane move. Looking at the plane, called Player in the scene, in the inspector, we could see it has a script component called Player Controller X added to it.

Double-clicking on the name of the script file (PlayerControllerX.cs) in the inspector allows us to open it. The code for moving the plane is in the Update() method:
// get the user's vertical input
verticalInput = Input.GetAxis("Vertical");
// move the plane forward at a constant rate
transform.Translate(Vector3.back * speed);
// tilt the plane up/down based on up/down arrow keys
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
We need to concentrate on the line that starts transform.Translate(…). The comment above it says “move the plane forward”, but the line itself is specifying Vector3.back as the direction of movement. Changing this to Vector3.forward makes it move in the right direction. The plane is still much too fast though. This line is asking the plane to move the distance specified by the speed parameter (by default 15m) every frame. What we need to do is to multiply here by Time.deltaTime, the amount of time since the last frame, to convert this movement into 15m per second, not per frame. Here’s the corrected line:
// move the plane forward at a constant rate
transform.Translate(Vector3.forward * Time.deltaTime * speed);
The next problem is that the plane turns on its own. In fact, although we’re gathering the value of the “Vertical” input axis in the code, pressing the arrow keys does nothing. We can identify the line of code that’s making the plane turn:
// tilt the plane up/down based on up/down arrow keys
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
This is asking the plane to rotate around Vector3.right (horizontally through the plane) by the number of degrees specified by the property rotationSpeed (with a default value of 100) every second. The multiplication of Time.deltaTIme is what makes it “every second” and not “every frame”, as before. So the plane is turning 100degrees every second, making it do a full loop approximately every three and a half second.
Nowhere here are the user inputs taken into account. How can we use them? Remember that the “Vertical” input axis in Unity works like this:
Input Option 1 | Input Option 2 | Axis Value |
W | Up-arrow | +1 |
<No key pressed> | <No key pressed> | 0 |
S | Down-arrow | -1 |
We’re gathering this axis value into a property called verticalInput already, we just need to use it. When multiplied in, it works like a switch. If its off (having the value zero) then no rotation happens. If it’s one or minus one, rotation happens in either a positive or negative direction:
// tilt the plane up/down based on up/down arrow keys
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime * verticalInput);
Now the plane flys correctly and responds to user input, but the it flies directly into the camera and then can’t be seen any more. First we need to grab the camera and move it to the side of the plane, rotating it around to point at the plane. This is better, but it still doesn’t move. The plane quickly flys beyond the area the camera can see. If we look at the camera in the inspector, we can see that it already has a script called Follow Player X on it:

It has a property called Plane, but nothing’s assigned there. We can set this by dragging and dropping the plane from the hierarchy, or by clicking the small circle icon on the right above and picking the “Player” object from the pop-up list. Running and testing this shows that the camera now follows the plane, but it’s right on top of the plane. It needs to be some distance away. Examining the FollowPlayerX.cs script we see at the top there’s a private property called offset:
private Vector3 offset;
that is used in the Update() method already:
transform.position = plane.transform.position + offset;
We just have to give it a value. The easiest way is to change private to public and then specify a value for the offset in the inspector.
The final challenge is to turn the plane’s propellor. Looking in the inspector, we can see this is its own object, a child of the “Player” object:

To make it spin, we can make a simple new script called SpinPropellor.cs and attach it to the propeller. This code works well:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpinPropellor : MonoBehaviour
{
public float spinSpeed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Rotate(Vector3.forward * Time.deltaTime * spinSpeed);
}
}
This is very similar to what we’ve done before, but the axis of rotation is the Vector3.forward here to make the propellor spin in the expected way. I found a value of 1000 or more was good for spinSpeed.
Note that although we’re moving the propellor ourselves, or at least rotating it, that doesn’t interfere with the fact that it’s moving with the plane, because it’s a child object.
Code for this Week
Updated code is on our GitHub repo: https://github.com/coderdojoathenry/Creators-2022 The problems with projects not loading correctly when downloaded has been corrected.