Developing an Avatar with Unity

Developing an Avatar with Unity

Learn how to create an avatar with Unity and enjoy it in virtual reality (VR) in this tutorial by Jonathan Linowes, a VR/AR evangelist, Unity developer, entrepreneur, and teacher.

Gaming is a common application of virtual reality, so you might as well start from there! With the help of this tutorial, you will give a character, Ethan, a life of his own. Well, sort of (or not), because he's going to become a zombie!

Bring Ethan to Life

Unity comes with a third-person character named Ethan. He's one of the Standard Assets in the Characters package. You can import him into your project.

To import, perform the following steps:

  1. Select Assets in the main menu bar and then navigate to Import Package | Characters.
  2. The Import dialog box pops up, containing a list of all the things that can get imported. Click All and then ImportThirdPersonController is a prefab (pre-built asset) located in the Project panel. You can find this by navigating to the Assets/Standard Assets/Characters/ThirdPersonCharacter/Prefabs folder.
  3. Drag a copy of ThirdPersonController into your scene. The exact x and z positions don't matter, but set y to 0 so that the character named Ethan is standing on GroundPlane. You can leave him at (2.200.75).

Now, try this out:

  1. Click on the Play icon at the top of the Unity window in the center, to start your game. Use the WAS, and D keys to move him aroundRun, Ethan! Run!
  2. Click on the Play icon again to stop the game and return to edit mode.

Ethan, the Walker

Now that you have brought Ethan to life, you can make him run around the scene if you have a hand controller with a thumbstick or touchpad, but that is not guaranteed on some VR devices. In fact, if you're viewing the scene with Google Cardboard, it's pretty unlikely that you'll have a handheld controller (notwithstanding the Bluetooth game controllers). However, you can consider another way to make him move around, using the direction of your gaze while wearing your VR headset.

Before you attempt this, you need to first transform Ethan into a zombie and have him walk around aimlessly without any user control. You can do this by giving him some AI and writing a script that sends him to random target locations. AI controllers and NavMesh are somewhat advanced topics in Unity, but you’ll get a glimpse into it just for fun. Besides, it's not as scary as zombies.

Artificially Intelligent Ethan

First, you must replace the ThirdPersonController prefab that you used initially with Unity's AI characterAIThirdPersonController, using the following steps. Unity uses the word artificial intelligence loosely to mean script-driven. You can do this by performing the following steps:

  1. Open your Unity project and have the Characters package imported from Standard Assets.
  2. In the Project panel, open the Standard Assets/Characters/ThirdPersonCharacter/Prefabs folder and drag AIThirdPersonController into the scene. Name it Ethan.
  3. In the Hierarchy panel (or in Scene), select the previous ThirdPersonController, (the old Ethan). Then, in the Inspector panel's Transform pane, choose the gear icon on the upper right of the Transform pane and select Copy Component.
  4. Select the new Ethan object (from the Hierarchy panel or Scene). Then, in the Inspector panel's Transform pane, choose the gear icon and select Paste Component Values.
  5. Now, you can delete the old Ethan object by selecting it from the Hierarchy panel, right-clicking to open options and clicking on Delete.

Note that this controller has a NavMesh Agent component and an AICharacterControl script. The NavMesh Agent has parameters for how Ethan will move around the scene. The AICharacterControl script takes a target object where Ethan will walk to. You can populate that as follows:

  1. Add an empty game object to the Hierarchy panel and rename it WalkTarget.
  2. Reset its Transform values to position (0,0,0) (using the gear icon in upper-right of the Transform pane).
  3. Select Ethan and drag WalkTarget into the Target property in the Inspector panel's AI Character Control pane, as shown here:

 

At this point, you have an AI character in the scene (Ethan). You can also create an empty game object that can be used as a navigation target (WalkTarget) initially in the center of your scene and tell the AI Character Controller to use this target object. When you run the game, wherever WalkTarget is, Ethan will go there but not yet.

The NavMesh bakery

Ethan cannot just go walking around without being told where he's allowed to roam! You need to define a NavMesh, a simplified geometrical plane that enables a character to plot its path around obstacles.

In your scene, Ethan is an agent. Where he's allowed to walk is the navmeshNote that he has a NavMesh Agent component and an AICharacterControl script. The NavMesh Agent has parameters for how Ethan will move around the scene.

Create a NavMesh by first identifying the objects in the scene that affect navigation by marking them Navigation Static and then baking the NavMesh, as follows:

  1. Select the Navigation panel. If it's not already a tab in your editor, open the Navigation window from the main menu by navigating to Window | Navigation.
  2. Select its Object tab.
  3. Select the Ground Plane in Hierarchy, then, in the Navigation window's Object pane, check the Navigation Static checkbox. (Alternatively, you can use the object's Inspector window Static dropdown list.)
  4. Repeat step 3 for each of the objects that should get in his way. An example is shown for the sphere.
  5. In the Navigation window, select the Bake tab and click on the Bake button at the bottom of the panel:

 

The Scene view should now show a blue overlay, where the NavMesh is defined, as shown in the following screenshot:

https://vlemonn.net/uploads/2018/8/t_30a4e3017bd9a30b3e712c4911d6a9.png

It’s time to test this out. Ensure that the Game panel's Maximize on Play is deselected. Click on the Play mode button (the triangle at the top of the editor). In the Hierarchy panel, select the WalkTarget object and ensure that the Translate gizmo is active in the Scene panel (press the W key on keyboard). Now, drag the red (x) and/or the blue (z) arrow handles on the WalkTarget object to move it around the floor plane. As you do, Ethan should follow! Click on Play again to stop Play Mode.

A Random Walker in Town

You will now learn to write a script that moves the WalkTarget object to random places.

Writing scripts is an important part of developing with Unity. If you've done anything more that tinker with Unity, you've probably already written at least some scripts. You are going to use the C# programming language for this.

For this first script, you can attach the script to the WalkTarget object, as follows:

  1. Select the WalkTarget object in the Hierarchy panel or the Scene view.
  2. In its Inspector panel, click on the Add Component button.
  3. Select New Script (you may need to scroll down to find it).
  4. Name it RandomPosition.
  5. Ensure that the C Sharp language is selected.
  6. Click on Create and Add.
  7. This should create a script component on the WalkTarget object. Double-click on the RandomPosition script in the slot to the right of Script in the Inspector pane to open it in your code editor.

The RandomPosition Script

Since you want to move the WalkTarget object to a random location so that Ethan will head in that direction, wait a few seconds, and move the WalkTarget object again. That way, he'll appear to be wandering around aimlessly. You can achieve this with a script. Here is the finished version first, and you can go through it line by line. The RandomPosition.cs script looks like this:

using UnityEngine; 
using System.Collections; 
 
public class RandomPosition : MonoBehaviour { 
 
  void Start () { 
    StartCoroutine (RePositionWithDelay()); 
  } 
 
  IEnumerator RePositionWithDelay() { 
    while (true) { 
      SetRandomPosition(); 
      yield return new WaitForSeconds (5); 
    } 
  } 
 
  void SetRandomPosition() { 
    float x = Random.Range (-5.0f, 5.0f); 
    float z = Random.Range (-5.0f, 5.0f); 
    Debug.Log ("X,Z: " + x.ToString("F2") + ", " + 
       z.ToString("F2")); 
    transform.position = new Vector3 (x, 0.0f, z); 
  } 
} 

This script defines a MonoBehaviour sub-class named RandomPosition. The first thing to do when defining the class is to declare any variables that you'll use. A variable is a placeholder for a value. The value can be initialized here or assigned elsewhere, just as long as it has a value before the script uses it.

The meat of the script is further down, the function named SetRandomPosition().

Create a GroundPlane plane of 10 units square, with the origin in the middle, so, any (x, z) location on the plane will be within a range fro-5 to 5 along each axis. The line float x = Random.Range (-5.0f, 5.0f) picks a random value within the given range and assigns it to a new float x variable. You can do the same thing to get a random z value.

The Debug.Log ("X,Z: " + x.ToString("F2") + ", " + z.ToString("F2")) line prints the x and z values in the Console panel when the game is running. It'll output something like X, Z: 2.33, -4.02 because ToString("F2") says round up to two decimal places. Note that you're using plus signs to combine the parts of the output string together.

You can actually move the target to the given location with the line transform.position = new Vector3 (x, 0.0f, z);. You can set the transform position of the object to which this script is attached to. In Unity, values that have an X, Y, and Z are represented by the Vector3 objects. So, you need to create a new one with the x and z values that you generated. You can use y=0 so that it sits on GroundPlane.

Each MonoBehaviour class has a built-in variable called this, which refers to the object that the script is attached to. This means when the script is a component of an object and appears in its Inspector panel, the script can refer to its object as this. In fact, this is so obvious, if you want to call functions on the this object, you don't even need to say it. You could have said this.transform.position = ..., but the this object is implied and is normally omitted. On the other hand, if you had a variable for some other object (for example, GameObject that;), then you'd need to say that when you set its position, like that.transform.position = ....

The last mysterious bit is how you handle time delays in Unity, using co-routines. This is a somewhat advanced coding technique, but very handy. In your case, the transform position should get changed once every five seconds. It's solved in several parts:

  1. In the Start() function, there's the line StartCoroutine (RePositionWithDelay());. co-routine is a piece of code that runs separately from the function from which it was called. So, this line kicks off the RePositionWithDelay() function in a co-routine.
  2. Inside this, there's a while (true) loop, which as you might guess, runs forever (as long as the game is running).
  3. It calls the SetRandomPosition() function, which actually repositions the object.
  4. Then, at the bottom of this loop, you can do a yield return new WaitForSeconds (5); statement, which basically says to Unity, hey, go do what you want for five seconds and then come back here so that I can go through my loop again.
  5. For all of this to work, the RePositionWithDelay co-routine must be declared as the IEnumerator type (because the documentation says so).

This co-routine/yield mechanism, although an advanced programming topic, is a common pattern in time-sliced programs such as Unity. You can save the script to a file named RandomPosition.cs.

You are now good to go. In the Unity editor, click on Play. Ethan is running from one place to another like a madman!

"Zombie-ize" Ethan!

OK, that's pretty random. Adjust the NavMesh steering parameters to slow him down to a nice zombie-like pace. For that, perform the following steps:

  1. Select Ethan in the Hierarchy panel.
  2. Navigate to Inspector | Nav Mesh Agent | Steering and set the following:
    • Speed0.3
    • Angular Speed60
    • Acceleration2

Play again. He has slowed down. That's better.

One more finishing touch: turn him into a zombie. You can select a texture image named EthanZombie.png that will help and perform the following steps:

  1. From the Assets tab on the main menu, select Import New Asset.... Navigate to the files folder where you have saved the file.
  2. Select the EthanZombie.png file.
  3. Click on Import. For tidiness, ensure that it resides in the Assets/Textures folder. (Alternatively, you can just drag and drop the file from Windows Explorer into the Project panel Assets/Textures folder.)
  4. In the Hierarchy panel, unfold the Ethan object (click on the triangle) and select EthanBody.
  5. In the Inspector panel, unfold the EthanGray shader by clicking on the triangle icon to the left of Shader.
  6. Select the EthanZombie texture from the Project Assets/Textures folder.
  7. Drag it onto the Albedo texture map. It's a small square just to the left of the Albedo label under Main Maps.
  8. In the Hierarchy panel, select EthanGlasses and uncheck it to disable glasses in the Inspector panel. After all, zombies don't need glasses!

Here is a sample portrait featured below. What'd you say? That's not a scary enough zombie?? Well, maybe he's just recently turned. Go ahead and make a better one yourself. Use Blender, Gimp, or Photoshop and paint your own (or even import a whole different zombie humanoid model to replace EthanBody itself):

Now, build the project and try it in VR. You will have a view from a third-person perspective. You can look around and watch what's going on. It's kind of fun, and it's pretty interesting. 

If you enjoyed reading this article, you can refer to Unity Virtual Reality Projects - Second Edition for creating more than 10 engaging projects with Unity 2018. This book will help you explore the latest features of Unity 2018 to create rich, interactive virtual reality experiences for Oculus Rift, HTC Vive, Daydream and Gear VR.

0 Comments
Leave A Comment

Please login to post your valuable comments.

Join the newsletter

Get the latest vLemonn news first

share