Interaction: First Person Navigation
Here we will try out first person navigation in Unity, using a starter asset. This is a very common way to navigate in 3D environments, and is used in many games — it can also be useful for us.
New Project
Let's start a new Unity project. This time, we use the Universal Render Pipeline (URP) template. This is a newer, more modern rendering pipeline that is more performant and flexible than the default one. It is also required for some of the features we will use later on.
Unity may ask to install some additional packages, which you should confirm.
Getting the Starter Asset
Using your Unity account, add the free, official starter asset from the Unity Asset Store: Starter Assets - First Person Character Controller | URP.
In your new project, you can access it through Window > Package Manager. Go to "My Assets" and search for "Starter Assets - First Person Character Controller | URP." Download it, and import it into your project using the buttons in the package manager.
For now, we can just select all the assets and import them in the next window that pops up.
Trying out the Starter Asset
Once Unity is done importing, we can try out the assets by finding the Playground scene under Assets > StarterAssets > FirstPersonController > Scenes
. Double-click it to load it.
You can try out the interactions afforded by the starter asset by pressing the play button. You can move around with the WASD keys, and look around with the mouse. You can also jump with the space bar, and walk faster by holding down the left shift key. Clicking inside the game window will lock the mouse cursor, so you can look around freely, and pressing escape will unlock it again.
You should try out different parameters for the movement, such as the walking speed, the jump height, and the mouse sensitivity. You can find these in the FirstPersonController component — it's attached to the PlayerCapsule game object in the hierarchy.
Adding more interaction
So far, so good — let's do something of our own. We will add a simple interaction to the scene, where we can click while viewing the environment and get a message about what we are looking at.
For that, we will add a new Script to the MainCamera game object. Create a new C# script called Clicker by clicking the Add Component button in the inspector, and selecting New Script.
Double click on it, and start adding code to it when it opens in VS Code. We will use the Update()
function to check for mouse clicks, and the Raycast()
function to check what we are looking at. We will also use the Debug.Log()
function to print out the name of the object we are looking at.
public class Clicker : MonoBehaviour
{
// Start is called before the first frame update
void Start ()
{
}
// Update is called once per frame
void Update ()
{
// Check if the mouse button is pressed down
if (Input.GetMouseButtonDown (0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit))
{
Debug.Log (hit.transform.gameObject.name);
}
}
}
Save the script, and go back to Unity. You should see the script in the inspector, and you can click the Play button to try it out. When you now click while in the game view, the name of the object in the middle of your view should be printed out in the console!
Making the objects interactive
It's good that we can see what we are looking at, but it would be even better if we could interact with it. For that, we will add a new component to the objects we want to interact with.
If you inspect how the scene is build, you will find a lot of objects called "Box_100x100x100_Prefab" or similar, and they all appear blue in the hierarchy. This means they are prefabs — a prefab is a template for a game object, and can be used to create many instances of the same object. This is useful for objects that are repeated many times, such as the boxes in the scene.
We can of course try to add a component to each of the boxes, but that would be a lot of work. Instead, we can add the component to the prefab, and it will be added to all instances of the prefab automatically. This can be done by selecting one of the boxes in the hierarchy, and finding its prefab: right-click on the object, go to Prefab > Select Asset.
You will find the original prefab assets under StarterAssets > Environment > Prefabs
. Select one of the "Box" objects there, and add a new "Clickable" script component to it.
You can immediately check in the hierarchy that all instantiated objects that come from this prefab now have the new component. Let's edit it in VS Code to make it do something.
In the code, we just add one public function, meaning it can be accessed from outside the script, e.g. by our Clicker script. For fun, let's make the object shrink to half its size when clicked.
public class Clickable : MonoBehaviour
{
// Start is called before the first frame update
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
public void OnClick ()
{
// shrink the object by 50%
transform.localScale = transform.localScale * 0.5f;
}
}
void Update ()
{
// Check if the mouse button is pressed down
if (Input.GetMouseButtonDown (0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit))
{
Debug.Log (hit.transform.gameObject.name);
GameObject obj = hit.transform.gameObject;
// Check if the GameObject has a Clickable component
if (obj.GetComponent<Clickable> () != null)
{
// Call the OnClick method of the Clickable component
obj.GetComponent<Clickable> ().OnClick ();
}
Transform objectHit = hit.transform;
if (hit.transform.gameObject.name == "Cube")
{
Debug.Log ("Cube clicked");
}
}
}
}
Save the script, and go back to Unity. You can now try out the interaction by clicking on the boxes in the game view in play mode. It should shrink to half its size!
You can attach the same script to other prefabs in the asset folder, and try out different interactions. You can also try to make the boxes grow again when clicked a second time, or make them disappear, or change color, or whatever you like.
For that you may need to give the scripts some variables about its state, e.g. a boolean variable that is set to true when the object is clicked, and false when it is clicked again. You can then check this variable in the OnClick()
function to decide what to do. Here is an example:
public class Clickable : MonoBehaviour
{
public bool clicked = false;
// Start is called before the first frame update
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
public void OnClick ()
{
if (clicked)
{
// shrink the object by 50%
transform.localScale = transform.localScale * 0.5f;
}
else
{
// grow the object by 50%
transform.localScale = transform.localScale * 2f;
}
// toggle the clicked variable
clicked = !clicked;
}
}
Challenge
Can you come up with other interactions? Try to make the objects move, or change color, or change shape.