In this codelab, you create a cannon that will be controlled by a panel of buttons you can push. All the interaction will be done using the Google VR Unity SDK raycasters.

What you'll learn

Tell us a little about yourself

How will you use this codelab?

Only read through it Read it and complete the exercises

How would you rate your experience with building Unity applications?

Never tried Novice Intermediate Proficient

How would you rate your experience with Google Daydream?

Never tried Novice Intermediate Proficient

How would you rate your experience writing code?

Never tried Novice Intermediate Proficient

Hardware you'll need

Software you'll need

Enable Android USB Debugging

In order to run samples, you'll need to enable debugging over USB on your device. To do so:

  1. Go to Settings
  2. Go to About phone (usually at the bottom)
  3. Tap Build number (usually at the bottom) seven times. You should see a toast saying you are now a developer.
  4. Return to the previous screen to find Developer options at the bottom.
  5. From the Developer options menu, find USB debugging and turn it on.
  6. When you connect your phone to your development platform, you will need to authenticate debugging from the phone. Allowing this will enable your machine to control your device.

Download The Google VR SDK for Unity

You will need this SDK to enable Daydream development in Unity. To do so, download it as a .unitypackage to your computer.

Download the latest SDK release here

Starter Project

We've also provided a .unitypackage to help you check your work along the way. You can download it from GitHub.

Get the project

You can either download the starter project to your computer...

Download Project .unitypackage

...or clone the GitHub repository from the command line.

git clone https://github.com/googlecodelabs/daydream-picking-pushing.git

To get started, we'll need to create a new project from scratch. Go ahead a launch Unity.

  1. After unity boots up, you will be greeted with a welcome dialog. Click the New button at the top to setup a new project.
  2. Set the Project name to "daydream-picking-pushing"
  3. You can set the Location to whatever you prefer.

If this is your first time using Unity, or you are still a beginner, let's walk through some important parts of Unity.

Using the Default Layout

First off let's use the default layout for the editor. At the top right of the editor, you will see several drop downs. Click the Layout dropdown and select Default. This will arrange the editor windows for you.

Unity's Windows

In Unity, there's several windows you should be aware of. Feel free to explore the provided links, but don't worry if it feels like a lot, we'll walk you through some of the first time steps.

Building for Android

First thing we need to do is configure Unity to build the project for Android

  1. Click on File -> Build Settings
  2. Change the target platform by selecting Android under the Platform menu.
  3. Click on Switch Platform.
  4. If everything was setup correctly, it will look like this (note the Unity symbol to the right of Android).

Configuring the Player

  1. Click on Player Settings... at the bottom of the Build Settings window. It will update the Inspector window in the right panel with the PlayerSettings.
  2. In the Inspector window, expand the Other Settings.

  1. Check the box for Virtual Reality Supported.
  2. Click on the + button and select Daydream SDK.
  3. Set the Package Name attribute to "com.example.daydream.picking"
  4. Finally set the Minimum API Level to 24 or greater.

Importing the Google VR SDK

If you haven't done so already, grab the the latest version of the Google VR SDK for unity. The latest .unitypackage is available to download from GitHub here.

  1. Open the .unitypackage from Windows Explorer or MacOS Finder.
  2. Unity will extract the package and prepare it's files for import. You'll get a confirmation dialog first that list all the files. Click Import to proceed.

  1. After the import operation, you will now see a GoogleVR option appear in the system Menu.

Importing the Codelab Project

Now we'll repeat the process for the provided Codelab project. Importing this project into Unity will set up the editor with the proper setting and include some assets we'll use later on in the Codelab. If you haven't done so already, grab the .unitypackage from GitHub here.

  1. Open the daydream-picking-pushing.unitypackage from Windows Explorer or MacOS Finder.
  2. Click Import to proceed.

Open the starter scene

  1. Now that we've imported all the assets, we'll setup our main scene. In the Project Window, select the Scene folder
  2. Double click the Starter scene to open it. You can use the zoom slider at the bottom right to switch between icons and a list view of the assets in the folder.

  1. In the Hierarchy window, you should just have the Main Scene with an Environment Object and a Main Camera.

The scene provided has a trio of targets atop an icy island. The Game view should look like this, which will be the perspective of the player when it is run on the headset.

The Arm Model

When using Daydream, it's best to set up an arm model to mimic where the user's hand is. An arm model is a mathematical model for approximating the location of the user's hand in virtual space. The Daydream controller only has rotational values, but we can use that in combination with the headset's information to create an accurate estimate of where the user's hand is.

Working with Prefabs

In Unity, a Prefab is a form of a template. You can create prefabs and then re-use them multiple times in a scene without having to create them over and over again. Through the course of this Codelab, we will provide some prefabs already made for you to use, and walk through the construction of one later on.

Using the SDK Prefabs

In order to do this, there are some foundational prefabs that are needed in order to set up a Daydream Arm Model.

You can read more about the Daydream controller and the provided prefabs here and here. We'll add them to the scene now.

Adding the Prefabs to the Scene

  1. In the Project window, type "t:prefab GVR" in the search bar, which will find all prefabs with the phrase "GVR".
  2. If you see a lot of blue cubes and can't see the names, use the zoom slider to make them larger, or shrink them down to a list.
  3. Select the four prefabs we are using.

  1. Drag and drop them on the Hierarchy window. Don't worry about order, it is not important in this context. In the end your hierarchy will look something like this.

Setup the Player

When creating Daydream applications, you'll want to have a Player GameObject in every scene. The Player will consist of the two elements that the user will use to interact with the scene: the camera and the controller. The camera will be used to position the viewpoint of the headset, ie- the root/head. The controller will be a hierarchy that represents the user's arm in the scene.

  1. From the Menu, Choose GameObject -> Create Empty. You will see a new GameObject in the Hierarchy window.

  1. In the Inspector window, rename the object "Player".
  2. Set Position to (0, 1, 0)

  1. In the Hierarchy window, find the Main Camera GameObject
  2. Make the Main Camera GameObject a child of the Player GameObject by dragging onto the Player GameObject. The Player GameObject will be highlighted when it is properly dragged.

  1. In the Hierarchy window, select the Main Camera GameObject

  1. In the Inspector window, set Position to (0, 0, 0)
  2. Set Clipping Planes/Near to 0.01

  1. We also want to make the GvrControllerPointer GameObject a child of player. Drag it onto player as well.

  1. Set it's Position to (0, 0, 0)

Your hierarchy will look like this when you are done:

Now we are ready to build and run our first Daydream APK!

Building

  1. Connect your phone to your computer via USB.
  2. From the menu, select File > Build Settings. In the Build Settings window, click On the Build and Run button at the bottom right.
  3. In the file selection dialog, specify your desired location for the resulting APK file. Unity will build, install, and run the apk on your device.

Running

If you have not yet put your phone in your headset, do so now. Ensure the USB cable stays connected, and that the volume/power buttons are on the top. If you just see a black screen, double check to make sure the device is on!

Controllers

Controllers are a required component of Daydream apps, so if your device does not have a controller paired to it, you will see something like this:

Every Daydream View comes with a remote included. If you don't have access to a Daydream view, you can emulate the remote using the Controller Emulator APK.

Initial Orientation

If everything is going smoothly, you should see a landscape with a controller floating in front of you. Follow the instructions and you should then see your application.

If you don't see anything try pressing and holding the home button at the bottom of the controller. It will recenter your view based on your current orientation. You can hold the home button at anytime to recenter.

Check your Work

After you have calibrated your controller, you will see the Daydream controller being held in your hand.

Open the main scene

If you have ran into any issues, don't fret! We've supplied another scene for this point in the codelab. Even if everything is running smoothly, it's good to use at this point as we've organized the scene a little more.

  1. Now that we've imported all the assets, we'll setup our main scene. In the Project Window, select the Scene folder
  2. Double click the Main scene to open it. You can use the zoom slider at the bottom right to switch between icons and a list view of the assets in the folder.

  1. In the Hierarchy window, your hierarchy should look like this:

Adding the Physics Raycaster

Before we move, we need to do some quick housekeeping. We'll need to add a raycaster to the main camera GameObject. This component will send the appropriate events to objects that are being hit by the controller's raycasts.

  1. In the Hierarchy window, select the Player/Main Camera GameObject

  1. At the bottom of the Inspector window, click the Add Component button
  2. Type in "GvrPointerPhysicsRaycaster" and hit enter or click it to add it.

Creating our scripts

Next we need to make some scripts which will allow us to create custom components that will change the behavior of our objects. We'll flesh out the code in these scripts later on.

  1. In the Project window, right click the Assets folder -> Create -> Folder.
  2. Name the folder "Scripts"

  1. Right click again on the Scripts folder -> Create -> C# Script
  2. Name the script "Colorable"

  1. In the Inspector window, verify your script was created

  1. Later on, we'll add some more components. Since we are in the script creating mood, we'll add them now. Repeat the steps above to add three script called "Throwable", "Cannon", and "Pushable"

For this codelab, we will be making a cannon like component the user can interact with. First up we are going to create an cannonball object that we can use over and over.

Creating a Cannonball GameObject

In Unity, we need to create our Cannonball object. First we'll create the geometry.

  1. From the Menu, Choose GameObject -> 3D Object -> Sphere. There will now be a new Sphere GameObject in the Hierarchy window.

  1. In the Inspector window, rename the object "Cannonball"
  2. Set Position to (-0.7, 1, 1)
  3. Set Scale to (0.25, 0.25, 0.25)

  1. Click the Add Component button
  2. Type in "Rigidbody" and hit enter or click it to add it

  1. On the Rigidbody component, Set Collision Detection to Continuous

  1. Check your work by clicking the Play Button on the Toolbar.

While running, will see an cannonball roll in front of you in the Game view of Unity.

Creating a Prefab out of the Cannonball

Before we start with the cannon, we'll want to make the Cannonball a prefab, since we'll be creating one every time the cannon is fired.

  1. In the Project window, right click the Assets folder -> Create -> Folder.
  2. Name the folder "Prefabs"

  1. In the Hierarchy window, begin to drag the Cannon GameObject

  1. Drop the Cannonball GameObject to the Prefabs folder in the Project window.
  2. You will now see an Cannonball prefab in the project. We can use this over and over again at runtime.

The Two States

While we interact with the Cannonball, we'll want to change it's color to indicate its state. The state will be represented by changing its color, and we'll have two states:

Adding the Colorable Component

Now that we have the raycaster, we want our cannonball to react to it. To do this, we are going to create a new component called Colorable which will listen to and respond to events fired by the raycaster.

  1. In the Hierarchy window, select the Cannonball GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Colorable" and hit enter or click it to add it

  1. In the Colorable component, double click the Script field to open up the scripting editor.

Now that you are in the coding editor, you will see an initial class template like so. Next let's flesh out the code!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Colorable : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

  }
}

Updating the State

  1. In order to change the color of the Cannonball, we'll need a reference to the renderer's material, so add a field of type Material.
  2. Add two fields to store the highlighted and touched colors.
  3. We'll also want to store the original color of the material, so cache that value privately as well.
  4. For our final fields, we'll need to keep track of if the object is highlighted and/or touched, so add two bool fields to track that.
// for changing the color
private Material _material;

// the colors to use when highlighting/touching
public Color highlightedColor = Color.green;
public Color touchedColor = Color.blue;

// the original color of the material, which will be restored if the object isn't highlighted/touched
private Color _originalColor;

// for tracking the state
private bool _isHighlighted;
private bool _isTouched;
  1. In the Start method, we'll want to cache the material and original color values.
// Use this for initialization
void Start () {
  _material = GetComponent<Renderer>().material;
  _originalColor = _material.color;
}
  1. Next, add two setter methods for highlight and touched:
public void SetIsHighlighted(bool value) {
  _isHighlighted = value;

  UpdateColor();
}

public void SetIsTouched(bool value) {
  _isTouched = value;

  UpdateColor();
}
  1. Finally, add the UpdateColor method
private void UpdateColor() {
  if (_isTouched) {
    _material.color = touchedColor;
  }
  else if (_isHighlighted) {
    _material.color = highlightedColor;
  }
  else {
    _material.color = _originalColor;
  }
}

Connecting the Raycaster Events

Now that our script is fleshed out, we need to setup the Unity GameObject to call the appropriate methods.

  1. First we will need some using imports at the top of the file.
using UnityEngine.Events;
using UnityEngine.EventSystems;
  1. Next we will an extension to the GameObject class to help connect the events. Add this class to the bottom of the Colorable script file. It simply extends GameObject to add a simple AddListener method for readability.
public static class EventExtensions {

 public static void AddListener(this GameObject gameObject,
                                EventTriggerType eventTriggerType,
                                UnityAction action) {
   // get the EventTrigger component; if it doesn't exist, create one and add it
   EventTrigger eventTrigger = gameObject.GetComponent<EventTrigger>()
                            ?? gameObject.AddComponent<EventTrigger>();

   // check to see if the entry already exists
   EventTrigger.Entry entry;
   entry = eventTrigger.triggers.Find(e => e.eventID == eventTriggerType);

   if (entry == null) {
     // if it does not, create and add it
     entry = new EventTrigger.Entry {eventID = eventTriggerType};

     // add the entry to the triggers list
     eventTrigger.triggers.Add(entry);
   }

   // add the callback listener
   entry.callback.AddListener(_ => action());
 }

}
  1. Next, in the Colorable class, connect the events in Start method.
// Use this for initialization
void Start() {
  _material = GetComponent<Renderer>().material;
  _originalColor = _material.color;

  gameObject.AddListener(EventTriggerType.PointerEnter, () => SetIsHighlighted(true));
  gameObject.AddListener(EventTriggerType.PointerExit, () => SetIsHighlighted(false));
  gameObject.AddListener(EventTriggerType.PointerDown, () => SetIsTouched(true));
  gameObject.AddListener(EventTriggerType.PointerUp, () => SetIsTouched(false));
}

Check your work

Now when you run, you should see the color of the cannonball change when you hover over it.

Next we'll add the ability for the user to pick up the cannonball. We'll do this by adding a new component, Throwable, which will be similar to the Colorable component.

  1. In the Hierarchy window, select the Cannonball GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Throwable" and hit enter or click it to add it

  1. In the Throwable component, double click the Script field to open up the scripting editor.

Holding the Cannonball

First up, when the user presses down on the touchpad, we want the cannonball to attach to their hand. We'll add a Hold and Release method to do so.

  1. Add the using imports at the top of the file.
using UnityEngine.Events;
using UnityEngine.EventSystems;
  1. Add the Hold method. This method will take the cannonball, attach it to the controller and disable physics.
public void Hold() {
  // get the Transform component of the pointer
  Transform pointerTransform = GvrPointerInputModule.Pointer.PointerTransform;

  // set the GameObject's parent to the pointer
  transform.SetParent(pointerTransform, false);
  
  // position it in the view
  transform.localPosition = new Vector3(0, 0, 2);
  
  // disable physics
  GetComponent<Rigidbody>().isKinematic = true;
}
  1. Add the Release method, which will return the cannonball to world coordinate system and turn its physics back on.
public void Release() {
  // set the parent to the world
  transform.SetParent(null, true);

  // get the rigidbody physics component
  Rigidbody rigidbody = GetComponent<Rigidbody>();

  // reset velocity
  rigidbody.velocity = Vector3.zero;

  // enable physics
  rigidbody.isKinematic = false;
}
  1. Listen for the raycaster events in Start
// Use this for initialization
void Start() {
  gameObject.AddListener(EventTriggerType.PointerDown, Hold);
  gameObject.AddListener(EventTriggerType.PointerUp, Release);
}

Now if you run you should be able to pickup and drop the cannonball.

Adding momentum

Once you release the cannonball, it seems to lose all momentum. This is simply because there are no forces acting on the object when it is released. In order to maintain momentum, we'll need to keep track of the velocity of the object while the user is holding it. We can do this by calculating the average velocity over time.

  1. We'll need to keep track of two variables: the previous position and the calculated throw velocity. Add them to the Throwable script.
// the calculated velocity for when the user releases the GameObject
private Vector3 _throwVelocity;

// the position of the object during the previous frame.
private Vector3 _previousPosition;
  1. Next we'll calculate the average velocity and save the position in Update:
// Update is called once per frame
void Update() {
  // the velocity is based on the previous position
  Vector3 frameVelocity = (transform.position - _previousPosition) / Time.deltaTime;

  const int samples = 3;
  // average the velocity calculate over the last number of frames
  _throwVelocity = _throwVelocity * (samples - 1) / samples + frameVelocity / samples;

  // update previous position
  _previousPosition = transform.position;
}
  1. Finally, apply the velocity by adding this code at the end of Release:
// enable physics
rigidbody.isKinematic = false;

// throw the object when releasing while held
rigidbody.AddForce(_throwVelocity, ForceMode.VelocityChange);

Apply changes to the Cannonball prefab

We have made a bunch of modifications to the Cannonball GameObject in the scene. However, we also want to apply these changes to the Cannonball prefab that we created earlier. This way when we create more cannonballs dynamically, all the changes will be present.

  1. In the Hierarchy window, select the Cannonball GameObject.

  1. In the Inspector window, Click the Apply button to update the prefab.

Check your work

Now when you run you should have a throwable cannonball. You can toss it around a bit, but try not to let it fall, it's the only one you have! Next up we'll add a control button to the scene that we will use to fire cannonballs.

Adding the Controls prefab to the Scene

We've provided a control platform on which to place the button. We'll add it to the scene now.

  1. In the Project window, type "t:Prefab Controls" in the search bar, which will find the provided Controls geometry prefab.
  2. If you see a lot of blue cubes and can't see the names, use the zoom slider to make them larger, or shrink them down to a list.
  3. Select the Controls prefab.

  1. Drag and drop the prefab on the Hierarchy window. In the end your hierarchy will look something like this.

Adding the Button geometry

Back in Unity, let's add some geometry to represent a cannon.

  1. In the Hierarchy window, add a child cylinder object by right clicking on the GameObject Controls/Panel -> 3D Object -> Cube. There will now be a new Cube GameObject added as a child to Controls/Panel.

  1. In the Inspector window, rename the GameObject "Button"
  2. Set Scale to (0.25, 0.125, 0.25)

  1. In the Mesh Renderer component, set Materials/Element 0 to Google Red. We are going to assign this field using the Object Picker. To open it, click the small circle next to the field.

  1. You will now see the Object Picker. Similar to the Add Component menu, you can find the object you are looking for by typing it in. Ensure you are in the Assets tab.
  2. Type "Google Red" to find our material. Hit enter or click it to select it.

  1. Note the updated value of the field.

  1. Finally add a Colorable component, click the Add Component button
  2. Type in "Colorable" and hit enter or click it to add it.

In the Game view, you should see a blue panel with a red button on it. Let's add a little personality to the button.

Adding a Button Icon

  1. In the Hierarchy window, add a child plane object by right clicking on the GameObject Controls/Panel/Button -> 3D Object -> Plane. There will now be a new Plane GameObject added as a child to Controls/Panel/Button.

  1. In the Inspector window, rename the plane "Icon"
  2. Set Position to (0, 0.51, 0)
  3. Set Rotation to (0, 180, 0)
  4. Set Scale to (0.1, 0.1, 0.1)

  1. In the Mesh Renderer component, set Materials/Element 0 to fire using the Object picker

Now your button should have a blazing flame on it, a good icon for a fire button! If you run you will see that the button also changes color thanks to the Colorable component. We want the button to react more when the user clicks the touch pad, so let's make it respond to touches.

Adding the Pushable Component

  1. In the Hierarchy window, select the Controls/Panel/Button GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Pushable" and hit enter or click it to add it

  1. In the Pushable component, double click the Script field to open up the scripting editor.

Animating the Button

  1. Add the using imports at the top of the file.
using UnityEngine.Events;
using UnityEngine.EventSystems;
  1. First off we're going to need two fields, one to track the animation time, and another to track what speed the time is animating, be it positive or negative.
// the current time value
private float _animationTime = 0;

// the velocity in which the animation value will change
private float _animationVelocity;
  1. Next up we'll add a method UpdateAnimationTime to update the animation time. We'll apply the animation velocity and clamp it to a value between 0 and 1.
private void UpdateAnimationTime() {
  // if pushed, time moves forwards, if not, time moves backwards
  float timestep = _animationVelocity * Time.deltaTime;

  // calculate the new animation time and clamp it to [0..1]
  _animationTime = Mathf.Clamp(_animationTime + timestep, 0, 1.0f);
}
  1. Once we have our animation time, we'll update the transform to animate the button. We are going to use a unity helper function Vector3.Lerp to linearly interpolate between the original position of the object and the pushed position. We'll cache the original position and calculate the pushed position based on the transform of the object.
// store this so we can lerp between it and the pushed position
private Vector3 _originalPosition;

private void UpdateTransform() {
  // we will move the object 0.5 units based on its scale
  float pushDistance = 0.5f * transform.localScale.y;

  // determine the direction from the object's rotation and the up vector
  Vector3 pushDirection = transform.localRotation * Vector3.up;

  // determine where the new position will be based on the direction and distance
  Vector3 pushedPosition = _originalPosition - pushDirection * pushDistance;

  // set the local position to the lerp between the original and pushed position
  transform.localPosition = Vector3.Lerp(_originalPosition, pushedPosition, _animationTime);
}
  1. To get the button to animate, we'll need to call our update methods in the Update method.
// Update is called once per frame
void Update() {
  UpdateAnimationTime();

  UpdateTransform();
}
  1. Finally, in the Start method, we need to hook the component up to the raycaster events. When it receives the Down/Up command we'll set the animation velocity value to -5/5, respectively. We'll also cache the original position value.
// Use this for initialization
void Start() {
  _originalPosition = transform.localPosition;

  gameObject.AddListener(EventTriggerType.PointerDown, () => {
    _animationVelocity = 5.0f;
  });
  gameObject.AddListener(EventTriggerType.PointerUp, () => {
    _animationVelocity = -5.0f;
  });
}

If you run now, you will notice that the button will animate when the user presses the touchpad.

Firing Events from the Button

As a last step, we'll add some events that will fire when the button is pushed.

  1. Generally, buttons have three events, a one shot when the button is pushed, and when it is released, as well as a continuous event that is fired every frame the button is pushed.
// fired once when the button transitions to the down state
public UnityEvent onPressed;

// fired every frame the button is in the down state
public UnityEvent onDown;

// fired once when the button transitions out of the down state
public UnityEvent onReleased;
  1. Since we are animating the button, we don't want to consider the button ‘down' until it has been depressed for a certain amount. In this case, we'll wait until the button is 90% pushed before it is considered ‘down'. We also need the previous frame's animation time to determine when the threshold is crossed to send the one-shot events.
private void CheckForEvents(float previousAnimationTime) {
  // when the animation time crosses this threshold, it will be considered pushed
  const float pushThreshold = 0.9f;

  // calculate before and after states
  bool wasDown = previousAnimationTime > pushThreshold;
  bool isDown = _animationTime > pushThreshold;

  // send press event if first frame pressed
  if (!wasDown && isDown) {
    onPressed.Invoke();
  }

  // always send down event if down
  if (isDown) {
    onDown.Invoke();
  }

  // send released event if first frame released
  if (wasDown && !isDown) {
    onReleased.Invoke();
  }
}
  1. Finally we need to add the calls to Update. Note that we are caching the value of the animation time before we update it in order to determine if the events need firing.
// Update is called once per frame
void Update() {
  // store the previous animation time for later
  float previousAnimationTime = _animationTime;

  UpdateAnimationTime();

  UpdateTransform();

  CheckForEvents(previousAnimationTime);
}

Now that our events are firing, let's add a cannon that we can fire!

Adding the Cannon geometry

Back in Unity, let's add some geometry to represent a cannon.

  1. From the Menu, Choose GameObject -> 3D Object -> Sphere. There will now be a new Sphere GameObject in the Hierarchy window.

  1. In the Inspector window, rename the sphere Cannon
  2. Set Position to (0, 0, 3)

  1. Remove the Sphere Collider component by clicking the Gear Icon -> Remove Component

  1. In the Mesh Renderer component, set Materials/Element 0 to Blue Grey using the Object Picker

  1. In the Hierarchy window, add a child cylinder object by right clicking on the GameObject Cannon -> 3D Object -> Cylinder. There will now be a new Cylinder GameObject added as a child to Cannon.

  1. In the Inspector window, rename the cylinder Barrel
  2. Set Position to (0, 0.7, 0)
  3. Set Scale to (0.5, 1, 0.5)
  4. Remove the Capsule Collider component by clicking the Gear Icon -> Remove Component

  1. In the Mesh Renderer component, set Materials/Element 0 to Blue Grey using the Object Picker

  1. Finally, let's check the cannon's pivot. In the Hierarchy window, select the Cannon GameObject.

  1. In the Inspector window, click on the Rotation/X value and drag with the mouse. Notice how the cannon rotates. Before moving on, set the Rotation to (45, 0, 0)

That about does it for the Unity side of the setup. Next we'll add a script to the cannon.

Adding the Cannon Component

  1. In the Hierarchy window, select the Cannon GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Cannon" and hit enter or click it to add it

  1. In the Cannon component, double click the Script field to open up the scripting editor.

Firing Cannonballs

  1. Add a field of type GameObject to point to the cannonball prefab. This is so we can make cannonballs dynamically at runtime each time the cannon fires.
// the prefab that holds the cannonball
public GameObject cannonballPrefab;
  1. Add a method to fire a cannonball. This will create a cannonball using the prefab, and apply a velocity based on the orientation of the cannon.
// fire a cannonball!
public void Fire() {
  // create a cannonball at the current position/rotation
  GameObject ball = Instantiate(cannonballPrefab, 
                                transform.position, 
                                transform.rotation);

  // get the rigidbody physics component
  Rigidbody cannonballRigidbody = ball.GetComponent<Rigidbody>();

  // apply the Velocity
  cannonballRigidbody.AddForce(Velocity, ForceMode.VelocityChange);
}
  1. Add a property to calculate the velocity of the cannonball.
private float _force = 20;

protected Vector3 Velocity {
  get {
    return transform.localToWorldMatrix * Vector3.up * _force;
  }
}

Assigning the Cannonball Prefab

Let's switch back to the Unity to set up the Cannon object in the scene.

  1. In the Hierarchy window, select the Cannon GameObject

  1. In the Inspector window, find the Cannon Component. Note the new Cannonball Prefab field.

Now the cannon is hooked up to create cannonballs.

Now we have the button and the cannon setup. All that is left is to connect the two via events.

  1. In the Hierarchy window, select the Controls/Panel/Button GameObject

  1. In the Inspector window, find the Pushable component and note the three event listener fields. We'll add a listener by clicking on the plus button under the On Pressed event.
  2. This will add a listener to the event. Next we need to assign the callback object by clicking on the small circle and to open the Object Picker.

  1. This time we are picking an object from the Scene, so ensure the Scene tab is selected.
  2. Type "Cannon" to find our object in the scene. Hit enter or click it to select it.

  1. Note the updated field in the Inspector window. Add the callback by clicking No Function -> Cannon -> Fire (). In the end your component should look like this.

Now when you run you can finally fire the cannon!

Now that we have our fire button we can hit the 500 target. But we are rather restricted by just the single angle we can fire from. Let's start adding some more buttons to rotate the cannon.

Expanding the Cannon script

First up let's add some methods to the Cannon script to allow for manipulation of rotation.

  1. In Cannon.cs, add a general Rotate method. This will allow us to rotate the cannon on the x and y axes. Note we are multiplying by delta time. Since we'll be calling this from a callback that is triggered by an event during the Update phase, we'll want to apply the appropriate timestep.
private void Rotate(float x, float y) {
  Vector3 transformEulerAngles = transform.eulerAngles;
  transformEulerAngles.x += x * Time.deltaTime;
  transformEulerAngles.y += y * Time.deltaTime;
  transform.eulerAngles = transformEulerAngles;
}
  1. Next let's add some methods to rotate left and right. We'll also add a constant to define the rotational velocity.
private const float RotationalVelocity = 50;

public void RotateClockwise() {
  Rotate(0, RotationalVelocity);
}

public void RotateCounterClockwise() {
  Rotate(0, -RotationalVelocity);
}

Now let's add some more buttons!

Adding a Rotate Counter Clockwise Button

We're going to start duplicating the fire button we just created to add a left and right rotation button to the scene.

  1. In the Hierarchy window, right click and choose Controls/Panel/Button -> Duplicate. This will create another button in the exact same position.

  1. In the Inspector window, rename the button, "Rotate Counter Clockwise"
  2. Set Position to (-0.25, 0, 0)
  3. Set Scale to (0.125, 0.125, 0.125)

  1. In the Mesh Renderer component, set Materials/Element 0 to Google Yellow using the Object Picker

  1. Since we duplicated the button, the fire callback was also copied. Click the gray box of the callback under On Pressed () to highlight it blue.
  2. Click the Minus button to remove the callback

  1. Now this time, connect the On Down event to call the Cannon.RotateCounterClockwise method. Click on the plus button under the On Down event.
  2. Set the callback object to Cannon using the Object Picker.
  3. Note the updated field in the Inspector window. Add the callback by clicking No Function -> Cannon -> RotateCounterClockwise(). In the end your component should look like this.

Finally, let's change the icon of the button.

  1. In the Hierarchy window, select the Controls/Panel/Rotate Counter Clockwise/Cube/Icon GameObject

  1. In the Mesh Renderer component, set Materials/Element 0 to rotate_left using the Object Picker

In the Game view, you should now see a second button on the controls. It will also cause the cannon to rotate if you try running, but let's add the other button first!

Adding a Rotate Clockwise Button

  1. First, rename our original Button GameObject to "Fire Button" by right clicking Controls/Panel/Button -> Rename.
  2. Next Duplicate the new button we made by right clicking Controls/Panel/Rotate Counter Clockwise -> Duplicate

  1. In the Inspector window, rename the duplicate, "Rotate Clockwise"
  2. Set Position to (0.25, 0, 0)
  3. Flip the x scale by setting Scale to (-0.125, 0.125, 0.125)

  1. Change the event listener in the Pushable scripts to call the Cannon.RotateClockwise method.

Build and Test

Now you should have a fully controllable cannon! Next we'll add a little polish

Simulating the Trajectory

Next up we're going to add some visual feedback when aiming the cannon, as well as how an cannonball moves. First up, we'll draw a trajectory line to estimate where the cannonball will travel when fired. We'll do this with Unity's LineRenderer.

  1. In Cannon.cs, flesh out Start to fetch and store a reference to the LineRenderer.
private LineRenderer _trajectoryLineRenderer;

// Use this for initialization
void Start() {
  // get the line renderer for the trajectory simulation
  _trajectoryLineRenderer = GetComponent<LineRenderer>();
}
  1. Next, in Update, we'll want to simulate the path of the object and store the result as a list of points in the LineRenderer. The calculation takes the position and rotation of the cannon and to estimate where the cannonball will travel. It does this by stepping forward in time and calculating the new position and velocity.
// Update is called once per frame
private void Update() {

  const int numberOfPositionsToSimulate = 50;
  const float timeStepBetweenPositions = 0.2f;

  // setup the initial conditions
  Vector3 simulatedPosition = transform.position;
  Vector3 simulatedVelocity = Velocity;

  // update the position count
  _trajectoryLineRenderer.positionCount = numberOfPositionsToSimulate;

  for (int i = 0; i < numberOfPositionsToSimulate; i++) {
    // set each position of the line renderer
    _trajectoryLineRenderer.SetPosition(i, simulatedPosition);

    // change the velocity based on Gravity and the time step.
    simulatedVelocity += Physics.gravity * timeStepBetweenPositions;

    // change the position based on Gravity and the time step.
    simulatedPosition += simulatedVelocity * timeStepBetweenPositions;
 }
}

Adding the Line Renderer in Unity

Back in Unity, we need to add the LineRenderer to our Cannon GameObject.

  1. In the Hierarchy window, select the Cannon GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Line Renderer" and hit enter or click it to add it

  1. In the Line Renderer component Set the Materials/Element 0 to ControllerLaser using the Object Picker.
  2. Set Width to 0.2
  3. Next, click on the white box next to Color to edit the gradient.

Creating a Color Gradient

Now we're going to make the laser look nice by using a Color Gradient.

  1. The last step will have brought up the Gradient editor. The bottom markers are for colors, and the top markers are for alpha values.
  2. Click on the left side color marker to edit that color
  3. Click on the Color box, which defaults to white.

  1. This will bring up the color editor

  1. Set the (R, G, B) values to (0, 255, 0), which is pure green (or any color you'd like!).

  1. Next, we'll make the color fade out as time passes. Close the color editor and your gradient will have changed. Click on the top right marker to edit the end alpha value.
  2. The color field will have been replaced with an alpha slider. Set the alpha value to zero and you will see a nice gradient fade out the green color.

  1. In the end, your component should look like this. Double check your Color field!

If you run now, you will see a nice green laser rendering from the cannon.

Adding a Trail Renderer to the Cannonballs

When you fire a cannonball it's hard to keep track of it. We can add a TrailRenderer component rather easily to help out with that. A TrailRenderer is just a LineRenderer that updates over time based on the object's position. We'll add one to the Cannonball prefab. A lot of these steps will be similar to the trajectory renderer.

  1. In the Hierarchy window, select the Cannonball GameObject.

  1. In the Inspector window, click the Add Component button
  2. Type in "Trail Renderer" and hit enter or click it to add it

  1. Set the Materials/Element 0 to ControllerLaser using the Object Picker
  2. Set Width to 0.2
  3. Set Time to 2
  4. Make the Color field a blue gradient similar to the one we just created for the cannon. Use RGB value (0, 0, 255) for the color. In the end, your component should look like this:

  1. Click the Apply button to update the prefab.

  1. Speaking of which, we probably don't need our cannonball floating around anymore, so you can remove it from the scene. In the Hierarchy window, right click on the GameObject Cannonball -> Delete.

Now that you have a trail renderer, you will see more clearly where the cannonball is moving!

This concludes the codelab, but here are some tasks you can try to go a little further.

  1. Here's some code to add to Cannon.cs
private const float ForceChangeVelocity = 20;

public void IncreaseForce() {
  _force += Time.deltaTime * ForceChangeVelocity;
}

public void DecreaseForce() {
  _force -= Time.deltaTime * ForceChangeVelocity;
}

public void RotateUp() {
  Rotate(RotationalVelocity, 0);
}

public void RotateDown() {
  Rotate(-RotationalVelocity, 0);
}
  1. Make the controls larger, and add more buttons to the controls. There's some extra icons and color provided.
  2. Try to make it looks like this!

  1. If you want to just skip to the good stuff, we've included a completed prefab, Complex Panel. Just drag it to the Hierarchy window. You still need to wire everything up!

You did it! You've finished the codelab and successfully created a scene in Unity with some interesting interactions for the player using the Daydream controller.

Beyond

If you are looking for some more interesting things to do try:

Additionally, if you want to explore the Daydream platform further, check out our documentation here.

Tell us how it went!

Were you able to complete the codelab?

Yes! Yes, with some issues. Nope!

What did you think about the amount of code?

Just Right Too Little Too Much

What did you think about the amount of Unity setup?

Just Right Too Little Too Much

Overall, are you glad you did this codelab?

Yes! No...