Howdy, fellas ! Today, after no less than five Unity articles having nothing to do with computer graphics whatsoever, I’m finally going to introduce you to 3D graphics. All good things come to those who wait. Of course, all bad things also come to those who wait… so why wait ? Food for thought, my friends, food for thought…
3D graphics in a nutshell
You might think 3D graphics is complicated. Well it’s not. And that’s because its concepts are all emulations of real-life concepts you’ve been familiar with ever since you’ve opened your eyes to this terrifyingly beautiful world.
When you program 3D graphics, you aim to simulate a scene in the real world you’d see with your real eyes. So let’s start there. What’s in a real-life scene ? Why are you seeing what you’re seeing ?
You are surrounded by things : the sky, the planet and everything on it. There is light, otherwise you wouldn’t be able to see any of it. And of course you have your wide-opened peepers. And you can move those peepers around using your body.
A 3D graphics engine emulates all of that : it represents things using 3D geometry (to give them volume) and 2D texture graphics (to give them, well, texture). It simulates light sources to determine what things are visible and how. It simulates eyes or cameras to give you a 2D representation of a 3D scene that maps directly to your real-life retinas, by way of a computer display.
Since light flies straight, all of this emulation ends-up taking the form of trigonometry. Simple but tedious, really tedious. And that’s why we have things like OpenGL and Direct3D. And then Unity adds a layer of abstraction on top of them so you never need to experience high-school math class PTSD.
Your application (or game) is essentially a virtual world made from scenes. Each scene starts in a default state that is represented as a hierarchy of game objects. As the player interacts with the scene, these game objects change. They can change position or shape or color or any other property but they can also be created and deleted on the fly.
In the Unity editor’s Hierarchy explorer (the left panel) you can see all the game objects that will be present when the scene starts. For reasons I’ve just stated, there needs to be at least one camera and one light source in there for 3D rendering to take place. But you can add anything else you want.
If you click on any game object and look at the Inspector panel (on the right) you’ll notice that each game object is made of components. Some components are very generic and found in all game objects, others are specific to certain game objects. You can even add components to game objects : our scripts, for example, when we drag and drop them onto an object.
As a programmer, you will control your scenes’ game objects through their components. And of course, because this is central to making a video game, Unity makes this very logical and very easy for you.
Let’s try with an example !
I know you don’t trust me. Must be my name. So let’s have you witness my words come true.
As usual, this won’t be something pretty but it will teach you a lot and, hopefully, dissipate any lingering doubts as to how easy 3D graphics can be.
We’re going to program camera controls that will allow us to navigate a Unity scene as if playing a first-person video game. That will give us the ability to change viewpoint in real time as our application runs. And in that scene, we’ll place a simple object and animate it in real time.
Let’s be about it !
Setting up the project
Launch the Unity editor and create a new 3D project. Because project names are forever destined to be bland, I say we call our project “Graphics_101“. There. Let artists worry about originality, we’re engineers baby !
Unless you’ve done something wrong (and we both know that’s impossible since visiting my site is a definitive sign of your infallibility) you now have a project with a default scene that contains two game objects : a camera and a light source.
Now what we need is some object to render. Game designers usually rely on artists modelling sexy ladies in Blender, but we are above such things. Or at least, we don’t have time for it just now. In the Unity editor’s Hierarchy panel, right click and navigate the contextual menu to “3D Object”. We’re going to add a 3D Text object to the scene.
And what do you know ! There’s now the words Hello World floating in the air in your scene !
The game object should have the default name “New Text“. Otherwise name it that.
We have a scene with a default camera and light source, and we’ve added an object to it. It’s now time to script them.
Controlling the camera’s rotation
From the assets explorer, create a new C# script and name it something suggestive, such as “CameraControl“. Drag and drop it onto the Main Camera in the scene’s hierarchy : this makes it a component of the camera. Now open that script.
You’ve probably noticed (because you’re so sharp it’s scary) that every game object in your scene has a Transform component. If you’re unfamiliar or if angles and cosines trigger your PTSD, a transform is essentially a mathematical operation you apply to the vertices of a 3D object to change its position (relative to the origin of coordinates), its orientation (relative to the X, Y and Z axes) and its scale.
As it happens, the main camera is a game object. If you change its transform, you change where it is and where it points. And because we’ve made our script a component of that camera, that transform is directly accessible.
First, add some members to your script to keep track of our camera’s orientation :
public float yaw = 0; public float pitch = 0;
And in the Update() method, let’s use the mouse axes from Unity’s Input Manager to change this orientation :
yaw += Input.GetAxis("Mouse X"); pitch -= Input.GetAxis("Mouse Y");
Remember : Unity’s input axes give you deltas, not absolute values, that’s why we need to accumulate (or integrate) them at every rendered frame.
Finally, still in Update(), just tell Unity to use these two values as part of a 3D vector to orient the camera :
transform.eulerAngles = new Vector3(pitch, yaw, 0); // roll axis stays put
And there it is, your basic first-person camera !
Controlling the camera’s translation
There again we could just assign values to the camera’s transform to give it a new position, but you can use a different approach : Unity also provides methods to perform incremental changes to a transform. And since the Input Manager also give you incremental data, that can make your code very simple. Add this to Update() :
transform.Translate(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));
Here, in a single statement, you’ve got your keyboard-controlled camera translations. Here’s how it works, in one sentence : two input axes corresponding to your keyboard arrows (or WASD keys) are captured and used to build a 3D vector that describes an incremental motion, which you then pass to the Translate method. What happens then is beyond your care : Unity will do its high-school math magic and your camera will change position. Simple as that.
Scripting the 3D text object
Getting hold the camera was easy : it was the parent object of our script, so “this.transform” or simply “transform” referred inherently to its transform. But now we want to access a different object. That’s actually easy too.
During your Start() method you can use Unity methods to find objects according to various criteria, including the name you give them in the Unity editor’s scene hierarchy panel. Let’s put that to use. First, add this member to your script :
public TextMesh textmesh;
This will hold the object we’re actually interested in modifying, which is the Text Mesh component of our “New Text” game object. Now, let’s code Start() to initialize it. First, we need to find the game object, knowing its name :
var gameobj = GameObject.Find("New Text");
And now we need to get a component of a specific type (TextMesh) from that game object :
textmesh = gameobj.GetComponent<TextMesh>();
You can use that component right away. For example, let’s give the text a font size that’s easy to read :
textmesh.fontSize = 100;
And we’re all set. Now let’s make things a bit more interesting.
Animating the 3D object
Since we have a text object, the obvious thing to do is make it display a counter. So we’ll count frames.
Add this member to the script :
public int frame;
Now in the Update() function, increment this counter at each frame and print its value into our text object :
frame++; textmesh.text = frame.ToString();
Once your application is running, I recommend you start by pressing the “down” arrow or the S key to move back a little, which will help you get the text object into view. Then go crazy with your mouse and keyboard.
In case you can’t find your text object anywhere, here’s some simple code you can put at the end of your Update() method to point the camera at it any time you hold down the left mouse button :
if (Input.GetAxis("Fire1") == 1) transform.LookAt(textmesh.transform);
All this does is poll the mouse button (via the Unity Input Manager) and then call a method of the camera’s transform that will recompute that transform to point at another game object. Note : you need to be sure your mouse cursor is inside the Unity editor’s player view when you press that button, of course.
You can now access the assets in a scene from your code. This basic ability gives you complete control over the scene and lets you display anything you want. It’s not just about changing transforms or displaying text. Look at any game object in the Unity editor’s Inspector : any property you can see, you can also change from code… and then some. Scripts themselves, as they are components, can control each other. It doesn’t get any more flexible than that.
3D graphics is awesome for engineering and scientific visualization because it maps more closely to our experience of reality than 2D graphics does. However, traditional software development tools don’t allow you to “do 3D” easily, so learning 3D ends-up representing a prohibitive time investment. With a game engine like Unity, not anymore. You could easily use it to plot 3D equations with interactive navigation, or to create engineering animations from CAD models.
I hope to see 3D graphics become common place among hackers and makers the way 2D graphics did. I feel it’s long overdue.
I haven’t decided yet on what topic to introduce next. Stay tuned for more information : I have a Twitter and a Facebook now, you can find the links at the top and bottom of this page ! You can also suggest a topic.