This is part three of a beginner-level series about Unity, aimed at existing .NET business developers, who are interested in dipping a toe into something different.
In Part 1 - Getting started, we explore how a business developer could make a start using Unity, look at the Editor and overview some of the common words that you’ll encounter.
In Part 2 - Scripting, we learn about some coding concepts that are applicable to Unity.
In Part 3 - A prototype mobile app, we work through the steps needed to make a super-simple application and deploy it to a mobile device.
In Part 4 -Logging and debugging with Android , we look at how we can attach the debugger and use logging - basic tools for any developer.
In Part 5 - Unity UI 101 , we take a first look at Unity UI and interact with a basic button control.
In Part 6 - Unity UI Scrolling List - Creating the Scene , we take on a slightly more complex project, by creating a scrolling list of items using Unity UI.
In Part 7 - Unity UI Scrolling List - Adding the Code , we finish the project started in Part 6, by writing a script to call a REST service and populate items in our UI.
Overview
In this article, we’ll be looking at using Unity to create a super-simple app for our mobile device.
As a reminder, this series is not intended to be an in-depth beginner guide to Unity. Instead, this is meant to be a birds-eye overview, orientated towards existing business developers. You’ll probably be the sort of person who already has a good feel for how software is created, but just wants an overview of the main features and semantics of how a Unity project hangs-together.
Create a new Unity project & set for mobile
- Start by using Unity Hub to generate a new project. Leave the default selection of “3D” for the project type.
- Select “File” → “Build Settings”
- Change the targeted platform to either “Android” or “IOS” (depending on which device we have in our hand).
- Click the “Switch Platforms” button (and wait a moment).
- Optionally, click “Add Open Scenes” button (only really relevant for larger projects with multiple scenes - our simple one-scene demo will work fine without setting this)
Enable developer mode on our phone
To progress with this project we need to be able to:
- deploy a development version of the app directly to our phone using USB.
- be able to debug the app running on the device.
To do this, we need to enable “Developer Mode”.
Depending on whether we are using Android or IOS, we need to perform some simple but hidden steps.
Android
- “Settings” → “About Phone” → “Software Information”
- Click “Build Number” seven times in a row.
- If successful we get a message saying that we are now a developer. We only need to do this process once.
IOS
- Connect our phone to our computer (which has ITunes running on it) using a cable.
- Press Home and Power at the same time for 10 seconds.
- Let go of the Power button, but keep holding Home down for a further 10 seconds.
- Now, let go of the Home button and the screen should go black (meaning it’s been forced into a firmware update (DFU) mode)
- On our computer, ITunes should report that it has detected the phone is in recovery mode. If we see this message and our phone screen has gone black, we are in developer mode.
Run a quick test deployment
At this point, our new Unity App is empty - but we can still check that we’ve got the basics in place by testing out that deployment works.
- Click “File” → “Build and Run”.
- When prompted, enter a filename for the build-settings save file. We can enter anything we like, but I usually just enter “android” or “ios”.
- Unity will now build the project, create a deployable package and deploy this package to our device.
- Behind the scenes, Unity is using build tools to create a package that is applicable to our phone (e.g. with Android, it uses the build-automation system Gradle to generate an Android Package File (APK))
- The deployment process is slow - be prepared to twiddle your thumbs.
- When we eventually see a result, the application should fire up (showing the Unity splashscreen, unless we are using a premium edition) followed by a running application that simply shows a grey-world with a blue sky. It’s not much, but it establishes that we can build and deploy without issue.
Add a 3D cube GameObject to our app
Now that we’ve established that we can deploy an empty application to our phone, let’s progress things, by demonstrating some new fundamentals
We’re going to add a super-simple 3D visual to our project.
- In the Unity Editor, find the Hierarchy View and right-click anywhere in the space underneath the default items “Main Camera” and “Directional Light”.
- Select “3D Object” then “Cube”
Let’s just pause a moment to talk about what we’ve just added.
- If we look at the Scene View we can confirm that, yes indeed, there is a cube there! Go ahead and use the mouse/trackpad in this panel, to move and zoom the camera around the cube to take a look around it if you like.
- We can read more at Unity Manual - Scene view navigation
There’s a bit more detail that’s worth drawing our attention to.
- If it isn’t already selected, click on the GameObject called “Cube” in the Hierarchy View
If we now look across to the other side of the screen, at the Components View, we can see that in addition to the “Transform” Component (that every GameObject has), when we created our new cube GameObject, Unity automatically added a couple of other Components.
As a reminder from the first article, everything that exists in the game world is a GameObject. However, it is the Components that define what the “thing” is going to be and how it behaves.
Back in the first article, we mentioned that one thing that was common to all GameObjects, is that they always have a “Transform” Component. Looking at the Inspector View, we can see the “Transform” Component at the top of the list.
- The values for “Position”, “Rotation” and “Scale” can be directly edited here. This is a good way to position things precisely, rather than moving them using the mouse in the Scene View.
- For the moment, we’ll ignore this “Transform” Component completely and just leave all of the settings at their default values.
- We can read more at Unity Manual - Transform
The bit that we may probably have expected to find was a Component called “Cube”. This identifies that this GameObject is a primitive 3D of type “Cube”.
- There are a handful of “Primitives” in Unity which include shapes such as “Cube”, “Sphere”, “Cylinder” etc.
- We can read more at Unity Manual - Primitive Objects
- There are a handful of “Primitives” in Unity which include shapes such as “Cube”, “Sphere”, “Cylinder” etc.
The component called “Mesh Renderer” is the bit that tells Unity how to visually render the object in the game world.
- It’s here that we define which Material to use.
- We can define how the GameObject interacts with lighting - e.g. does it cast a shadow?
- We can read more at Unity Manual - Mesh Renderer
The Component “Box Collider” is one way to describe how the object interacts with other objects in the game world.
- The Box Collider is one of several types of “Collider” that are related to the Unity physics engine.
- Without a Component that interacts with the physics engine, we can think of our object as behaving a bit like a ghost … we might be able to see it rendered visually, but it cannot interact with any other object. For example, it couldn’t bounce off other cubes.
- Of particular relevance to our phone application, if for example, our application required us to “tap on a cube” in order to select it - without a “Collider” there would be nothing for us to interact with.
- We can read more at Unity Manual - Colliders
Add a script that will rotate the cube
Now that we have a GameObject to work with, let’s progress the demonstration, by adding a C# script that will rotate the cube.
Any code provided in this article is “demoware” in order to retain brevity and focus. We make no effort to address issues of code robustness or error handling etc.
- Firstly, in the Project View, select the top-level folder called “Assets” and create a new sub-folder called “Scripts”. By default, there is already a sub-folder called “Scenes”, so this new folder will be a sibling to that.
- Next, select the new “Script” folder and right-click to show the context-menu. Select “Create” → “C# Script” and name the new script “RotatingCube”
Don’t worry about the actual C# code right now - we’ll come to that next. First, we need to associate the script with the GameObject.
In Unity things are commonly “plumbed together” in a very UI-orientated way.
Developers who have been in the industry for many years may recognise this visual approach to creating applications (e.g. VB6, WinForms, WebForms and Cocoa).
However, if you are a business developer who has only used technologies prevalent in the past decade, this may all feel a bit unfamiliar. If this is the case, you are likely to be more accustomed to configuring the various moving parts of your application together, purely using code (for example, using a Markup language such as HTML or XAML to describe the UI, which typically include identifying tags that correspond with matching field name in some form of View-Controller)
- With the new script created, we can now associate it by drag-and-dropping the “RotatingCube” Script item (from the Asset View) directly onto the “Cube” GameObject in Hierarchy View.
- Alternatively, if we already have the “Cube” GameObject highlighted - and we can already see all of the Components being listed in the Inspector View - we could drag-and-drop the “RotatingCube” script item onto the bottom of the Inspector View.
- Either way, we should see the new script Component showing in the Inspector View (see the following screenshot):
Let’s write some code to rotate the cube
With the solution/project open in Visual Studio, you should be able to see the newly-added file “CubeRotator.cs” in the Solution View and the actual C# code ready for editing.
Because we created the script using the Unity Editor, that script will already be templated ready for us to start working on it. For example, we’ll see that the class inherits from MonoBehaviour
. It should look very similar to the code below:
using UnityEngine;
public class CubeRotator : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
For the purpose of this guide, we don’t need to worry about what the
MonoBehaviour
base class represents, other than noting that- For our code to interact with the Unity engine, it needs to inherit from
MonoBehaviour
. MonoBehaviour
forms part of a stack of other Unity classes.MonoBehaviour
→Behaviour
→Component
- If we are writing our own code that doesn’t actually interact directly with Unity, it doesn’t need to inherit from
MonoBehaviour
- we’re free to write our own code however we wish. - We can read more at Unity Scripting Documentation - MonoBehaviour although this is more of a technical listing and is not very descriptive for beginners. This flowchart diagram is probably a more useful guide.
- For our code to interact with the Unity engine, it needs to inherit from
The templated class also comes with two placeholder methods:
- The
Start()
method contains code that is executed when the GameObject is instanced - The
Update()
method contains code that is executed as part of the game loop
- The
As a developer with some existing experience, our instinct will most likely be telling us that in order to manipulate our Cube object using code, we will need to somehow get a reference to it.
Next, we’ll look at two ways that we could go about doing this.
Referencing an object - approach #1
- Add the following code to the top of our new class
CubeRotator
. We want to create a new field of type GameObject that we can work with :
using UnityEngine;
public class CubeRotator : MonoBehaviour
{
public GameObject ourCubeObject;
void Start()
{ }
void Update()
{ }
}
- Save the changes to the code file and return back to Unity
- Make sure the Cube GameObect is selected in the Hierarchy View and look across to the “Cube Rotator” Component in the Inspector View.
- You should now see that the public field we added called “ourCubeObject” is showing in the Inspector - Notice how Unity has automatically extracted our camel-cased fieldname “ourCubeObject” and converted it into the more human-readable version “Our Cube Object”
We’ll plumb this code together in a moment, but let’s just quickly improve the presentation of code in the Unity Editor.
- If we use a
public
accessor for this field, this means that other parts of our code can access this field. This may not be desirable. - Instead, we should use the
[SerializeField] attribute, which exposes the field to the *Unity Editor* (at design-time) but lets us use a
private` accessor. We can also improve the human-readability of the fields displayed in the Unity Editor by including:
- a
[Tooltip]
attribute, for hover-over information in the Unity Editor a
[Header]
attribute which acts as a way to group fields together as sections in the Unity Editor.Go ahead and modify our code so it looks like the following:
- a
using UnityEngine;
public class CubeRotator : MonoBehaviour
{
[Header("Section for configuring Game Objects")]
[SerializeField]
[Tooltip("A GameObject that we will rotate in code")]
private GameObject ourCubeObject;
[SerializeField]
[Tooltip("A GameObject that is included for demonstration, but we won't use")]
private GameObject unusedCubeObject;
void Start()
{ }
void Update()
{ }
}
- Save the changes to the code, and once again return to the Inspector View. Things should now look like the following screenshot:
Now that our code is ready to receive a reference to a GameObject, let’s go ahead and actually connect things up.
- In the Unity Editor, locate the GameObject “Cube” in the Hierarchy View
- Drag the “Cube” from the Hierarchy View, across the screen, and drop it onto the rectangular setting box that corresponds with “Our Cube Object”.
- By default, the box will show the words “None (Game Object)”.
Referencing an object - approach #2
Using the Unity Editor to visually glue things together is a very common approach. However, it’s not the only way to obtain a reference to a GameObject or another Component
It’s possible to search for objects and components at runtime (a little bit like searching the DOM in HTML), thereby letting us locate things using only code.
- As a complete alternative to our previous example, above, go ahead replace all of our code with the following:
using UnityEngine;
public class CubeRotator : MonoBehaviour
{
private GameObject ourCubeObject;
void Start()
{
ourCubeObject = GameObject.Find("/Cube");
}
void Update()
{ }
}
To explain the above code:
- We can use the static
GameObject.Find()
method to locate a GameObject in the Scene at runtime. - We insert this code into the
Startup()
method so that it runs as soon as it’s available. - We use a forward-slash
/
in the path to indicate that we are looking for an object called “Cube” in the root of the Hierarchy.
- We could be as specific as required - for example
GameObject.Find(/SomeParentObject/SomeChildObject)
- We could be as specific as required - for example
- We can read more at Unity Scripting Documentation - GameObject.Find
Let’s get on with rotating that cube!
Now that we have created a reference to the ourCubeObject
GameObject, we can now interact with it using code.
- Edit our
CubeRotator
class so it looks like this:
using UnityEngine;
public class CubeRotator : MonoBehaviour
{
[SerializeField]
[Tooltip("The speed of rotation, in degrees per frame")]
private float rotationSpeed = 20.0f;
private GameObject ourCubeObject;
void Start()
{
ourCubeObject = GameObject.Find("/Cube");
}
void Update()
{
ourCubeObject.transform.Rotate(Vector3.right * (rotationSpeed * Time.deltaTime));
ourCubeObject.transform.Rotate(Vector3.up * (rotationSpeed * Time.deltaTime));
}
}
Let’s talk about the changes that we just made to the Update()
method:
- By referring to the
transform
property, we can change values such as “Position” and “Rotation”. In this example, we have used the
Transform.Rotate()
method to change the value of theGameObject.rotation
property (as opposed to attempting to update the value of therotation
value directly. This property is aVector3
object which is astruct
- so we won’t be able to work with it directly in the way in which we might initially assume (refer to Microsoft Documentation - Using Structs for an explanation.- We can read more at Unity Scripting Documentation - Transform.Rotate
Time.DeltaTime()
is a way of dealing with the framerate of the application and the passage of time in a game. We can’t assume that an app will always run at a certain framerate (for example, a demanding scene could reduce the framerate - or perhaps some other process causes the app to become “choppy”). Therefore, we useTime.DeltaTime()
to figure out how much time has elapsed since the previous frame.- We can read more at Unity Scripting Documentation - Time.DeltaTime
We’re getting very close to testing out our new project. Before we do that, we need to finish the process:
- Save the code and return back to the Unity Editor
- If not already selected, highlight the “Cube” in the Hierarchy View.
- Over in the Inspector View locate our “CubeRotator” Component.
- Enter a value of “10” in the field “Rotation Speed” (Notice that in our code we defined a default value of “20”, but we can specify different values here in the Unity Editor)
Test and redeploy the app to our mobile device.
This bit is easy;
To test on our computer first, simply press the “Play” button in the top-centre of the Unity Editor.
We should see the player start the game running on our computer and we should see our cube rotating.
If we are satisfied that everything seems to be working - and we are happy with the rotation speed, then go ahead and “Build and Run” the project, deploying the latest version to our mobile device.
Wrapping up
Hopefully, you’ve found this demonstration project to have been fairly straightforward to follow along with. We’ve actually covered a fair bit of ground, introducing various concepts and giving an overview of how several of the moving parts fit together.
A key take-away from this article should be that:
- In C# code, we can define and organise fields that can be exposed by the Unity Editor
- Using the Unity Editor we can connect references to GameObjects and Components, allowing us to then interact with those game-engine objects using our C# code.
- We can also use this mechanism to provide configuration values in the fields of a Component - this gives us a way to experiment with different settings (even at runtime) without having to leave the Unity Editor
In the next part of this series, we look at how to use the debugger and logging in Unity.