Using Unity* 3D Standard GUI with TouchScript Assets

By Lynn Thompson

Download PDF

The standard Unity* 3D graphical user interface (GUI) widgets respond to touch as if you had clicked them with a mouse using Windows* 8 Pen and Touch functionality, and you cannot at present configure them for multitouch with multiple gestures. The example in this article shows how to use the TouchScript Pan Gesture to enhance standard GUI objects. The resulting widgets provide the look and feel of the standard Unity 3D GUI widgets, and you can relocate them on the screen by dragging them (Pan Gesture). The example shows Unity 3D running on Windows 8, a proficient platform for providing users with GUI widgets they can customize in a flexible manner.

Creating the Example

The example begins by creating a few spheres and cubes in the view of the scene’s main camera. This scene is simple and contains only a few pieces of three-dimensional (3D) geometry that you can modify by manipulating standard Unity 3D GUI widgets. The main Unity 3D GUI widgets used are buttons, horizontal slider bars, and radio buttons. After each Unity 3D GUI widget has been configured, you then place a Unity 3D quad asset at the same location, with dimensions similar to the standard Unity 3D GUI widgets. You configure this quad with a TouchScript Pan Gesture that allows users to move it. The position of the quad asset feeds the location parameters of the standard Unity 3D GUI widget for which it has been configured and with which it shares a location. The result is a standard Unity 3D GUI widget that users can move around the screen through a TouchScript Pan Gesture. Figure 1 provides a screenshot of the example.

Three Unity* 3D standard GUI widgets
Figure 1. Three Unity* 3D standard GUI widgets

Add a Standard GUI Widget

Start by adding three GUI widgets in the OnGUI function. The first widget contains a panel and a few buttons to adjust the scale of the simple scene geometry. The second widget is a panel containing radio buttons for discretely changing the scale of the geometry in the scene. The third widget contains three horizontal slider bars that are tied to the scene geometry’s rotation around the x-, y-, and z-axes. Place these three widgets in the upper left, upper middle, and upper right areas of the screen. Their placement is based on a 1024x768 screen resolution.

Many resources are available to assist in configuring standard Unity 3D GUI widgets. The source code for the Unity 3D GUI widgets used in this example is provided in the accompanying Unity 3D project.

Configure TouchScript

This example adds Unity 3D quad primitives as the TouchScript target that facilitates the touch movement of the standard Unity 3D GUI widgets. You add these primitives programmatically, not in the Unity 3D editor. The code to add the quad used to move the upper left button GUI widget is as follows:

Public Class:
.
.
.
private GameObject buttonQuad;//Declare asset to receive gestures
//Declare variables to manipulate standard GUI position via gestures
private Vector3 buttonQuadStartPosition;
private float buttonQuadDeltaX;
private float buttonQuadDeltaY;
.
.
.
Start Function:
.
.
//Create asset to receive gestures
buttonQuad = GameObject.CreatePrimitive (PrimitiveType.Quad);

//Set the position vector of the asset receiving gestures to match the standard
//GUI position
buttonQuad.transform.position = new Vector3(-0.7f,2.25f,-10.0f);

//Add the TouchScript components to make the touch asset responsive to gestures
buttonQuad.AddComponent ("PanGesture");
buttonQuad.AddComponent ("PanScript");

//Initially position the touch gesture asset
buttonQuadStartPosition = buttonQuad.transform.position;
//Initialize the position change variables
buttonQuadDeltaX = 0.0f;
buttonQuadDeltaY = 0.0f;

//Make the touch gesture asset invisible
MeshRenderer buttonQuadRenderer = (MeshRenderer) buttonQuad.GetComponent ("MeshRenderer");
buttonQuadRenderer.enabled = false;
.
.
.
Update function:
.
.
//Set the position change variables. The 235 scaling factor is for a 1024x768
//screen resolution. In a production application this scaling factor would be
//set based on the resolution chosen by the application or user at launch.
buttonQuadDeltaX = -235*(buttonQuadStartPosition.x - 	buttonQuad.transform.localPosition.x);
buttonQuadDeltaY = 235*(buttonQuadStartPosition.y - buttonQuad.transform.localPosition.y);
.
.
OnGUI function:
.
.
////////////////////// Button Menu Begin ////////////////////////////////////
//Draw a standard GUI box at a position altered by the position of the asset
//receiving touch gestures
		GUI.Box(new Rect(10+buttonQuadDeltaX,10+buttonQuadDeltaY,240,160), "Button Menu");

//Draw a standard GUI button at a position altered by the position of the asset
//receiving touch gestures

		if(GUI.Button(new Rect(20+buttonQuadDeltaX,40+buttonQuadDeltaY,220,20), "Increase Scale (4x Maximum)"))
		{
			//While increasing the cube scale, limit the cube scaling
			//to be between 0.25 and 4

			if (scale < 4.0)
			{
				scale += 0.1f;
				cube01.transform.localScale += (new Vector3(0.1f,0.1f,0.1f));
				cube02.transform.localScale += (new Vector3(0.1f,0.1f,0.1f));
				sphere01.transform.localScale += (new Vector3(0.1f,0.1f,0.1f));
				sphere02.transform.localScale += (new Vector3(0.1f,0.1f,0.1f));

			}
			if (scale == 4.0f)
			{
				maxscale = true;
				minscale = false;
				defaultscale = false;
			}
			else
			{
				maxscale = false;
			}
			if (scale == 0.25f)
			{
				minscale = true;
				maxscale = false;
				defaultscale = false;
			}
			else
			{
				minscale = false;
			}
			if (scale == 1.0f)
			{
				defaultscale = true;
				maxscale = false;
				minscale = false;
			}
			else
			{
				defaultscale = false;
			}
		}
		
		if(GUI.Button(new Rect(20+buttonQuadDeltaX,80+buttonQuadDeltaY,220,20), "Decrease Scale (0.25x Minimum)"))
		{
			if (scale > 0.25)
			{
			//While decreasing the cube scale, limit the cube scaling
			//to be between 0.25 and 4

				scale -= 0.1f;
				
				cube01.transform.localScale -= (new Vector3(0.1f,0.1f,0.1f));
				cube02.transform.localScale -= (new Vector3(0.1f,0.1f,0.1f));
				sphere01.transform.localScale -= (new Vector3(0.1f,0.1f,0.1f));
				sphere02.transform.localScale -= (new Vector3(0.1f,0.1f,0.1f));
			}
			if (scale == 4.0f)
			{
				maxscale = true;
				minscale = false;
				defaultscale = false;
			}
			else
			{
				maxscale = false;
			}
			if (scale == 0.25f)
			{
				minscale = true;
				maxscale = false;
				defaultscale = false;
			}
			else
			{
				minscale = false;
			}
			if (scale == 1.0f)
			{
				defaultscale = true;
				maxscale = false;
				minscale = false;
			}
			else
			{
				defaultscale = false;
			}
		}

		//Create a button to exit the application
		if(GUI.Button(new Rect(20+buttonQuadDeltaX,120+buttonQuadDeltaY,220,20), "Exit Application"))
		{
			Application.Quit();
		}
		
		GUI.Label (new Rect(20,180,220,20),scale.ToString());
		////////////////////// Button Menu End//////////////////////////////////
.
.
.

The PanScript script programmatically added to the quads allows for the panning and drag-and-drop behavior of the quads. You can review this functionality in the accompanying example or the “Everything” example provided with the TouchScript package. The SGwTS.wmv video that accompanies this example shows the GUI widgets in use.

Example Enhancements

The most tedious step in creating this example is placing the quad behind the GUI widget. It’s a manual, trial-and-error process in which the x, y, and z values are changed until the quad is lined up with the standard Unity 3D GUI widget. This alignment is not valid if at application startup the user changes the screen resolution to something other than 1024x768. To enhance this example, you could use the Unity 3D GUI layout functionality followed by automatic placement of the affiliated TouchScript Pan Gesture touch target quad.

The quad used in the accompanying example was sized for the same width as the standard Unity 3D GUI widget and a larger height dimension. The result is “tabs” at the top and bottom of the widget that the user touches to drag the widget around the screen. You can adjust the position of the quad relative to the standard Unity 3D GUI widget to move the touch target point. For example, the quad could line up with the widget on the sides and bottom, moving the intended touch target to the top of the widget.

I say intended because in the accompanying example, the user can touch anywhere on the quad to move it and the affiliated widget, including the areas of the quad that occupy the same screen space as the widget. To limit the touch target points to those on the quad that extend beyond the screen space that both share, you can add a second “blocking” quad. This blocking quad would have the same dimensions as the standard Unity 3D GUI widget and be placed at the same location. The quad used to alter the position of the standard widget determines the position of this blocking quad. With this functionality in place, the blocking quad then uses the TouchScript Untouchable behavior. An example of this behavior is provided with the TouchScript Hit example. Implementing this functionality eliminates a flaw in the accompanying example where the slider widget moves when the horizontal slider bars are moved.

This method of using touch target quads and block quads can be extended to allow movement of user-configurable widgets. By stacking touch quads and block quads, users can move the GUI widget components independently of the GUI widget in its entirety. For example, a user can manipulate individual horizontal sliders independently of each other at the rectangle base. Similarly, you could use a custom Pan Gesture to limit the movement of the GUI widget component within the borders of the widget.

Touch Order

Remember that one of the GUI widgets you configured allows you to scale the geometry primitives in the scene. The left cube and right sphere have been configured with a Pan Gesture, and you can drag them around the scene as desired. The center cube and center sphere have not been configured with any TouchScript gestures and do not respond when touched. This behavior creates an issue, because if the scene geometry is scaled out sufficiently, the geometry engulfs the quads used to move the GUI widgets. If a user scales the geometry primitives to such an extreme and then drags a GUI widget on top of them, the next touch gesture that targets this area of the screen results in a touch gesture activating the geometry primitive, not the GUI widgets. Fortunately, you can use this touch gesture to move the geometry primitive from behind the GUI widget, allowing the widget to respond to touch gestures again.

If a user drags a GUI widget on top of one of the center primitives that has not been configured for touch gestures, the Widget will be stranded. You can resolve this issue by assigning the scene primitive to the TouchScript Untouchable Behavior by means of the Add Component button (see Figure 2). This configuration allows touch gestures to pass through the primitive to the GUI widgets that you have configured with a Pan Gesture. You can observe this behavior in the accompanying video, where a GUI widget dropped on the left cube or right sphere results in the next touch gesture moving the cube or sphere. A GUI widget dropped on the middle sphere (which has the Untouchable Behavior assigned) results in the next touch gesture moving the GUI widget. If the scale factor is large enough to make the middle cube engulf the unrendered quads and a GUI widget is dropped on the middle cube, the GUI widget is stranded.

You must use the TouchScript Untouchable Behavior in any scenario where you don’t want a scene asset to affect the GUI widget. For a first-person shooter (FPS) game using the GUI widgets described in this article, you would need to configure the TouchScript Untouchable Behavior for every scene asset with which the FPS’s main camera may come in contact.

Configuring a Unity* 3D scene asset to allow touch gestures
Figure 2. Configuring a Unity* 3D scene asset to allow touch gestures for objects behind the asset

Render Order

The visible component of the GUI widgets configured in this article are native Unity 3D GUI widgets constructed in the OnGUI function. As such, they will always be visible, and there is no need to configure a dedicated GUI widget camera to render a unique GUI widget layer.

Conclusion

The TouchScript package functions well when implemented in combination with the standard Unity 3D GUI widgets. You can use this combination in any number of ways to produce traditional GUI widgets that users can move around the screen through drag-and-drop-type gestures, saving the time and the effort necessary to create geometry for use with TouchScript gestures that result in a completely custom GUI widget. If you don’t require this level of customization, the method in this example provides a means of quickly generating GUI widgets that respond to drag-and-drop gestures and work smoothly and reliably on the Unity 3D–Windows 8 platform.

Related Content

About the Author

Lynn Thompson is an IT professional with more than 20 years of experience in business and industrial computing environments. His earliest experience is using CAD to modify and create control system drawings during a control system upgrade at a power utility. During this time, Lynn received his B.S. degree in Electrical Engineering from the University of Nebraska, Lincoln. He went on to work as a systems administrator at an IT integrator during the dot com boom. This work focused primarily on operating system, database, and application administration on a wide variety of platforms. After the dot com bust, he worked on a range of projects as an IT consultant for companies in the garment, oil and gas, and defense industries. Now, Lynn has come full circle and works as an engineer at a power utility. Lynn has since earned a Masters of Engineering degree with a concentration in Engineering Management, also from the University of Nebraska, Lincoln.

Intel, the Intel logo, and Ultrabook are trademarks of Intel Corporation in the U.S. and/or other countries.
*Other names and brands may be claimed as the property of others.
Copyright © 2014. Intel Corporation. All rights reserved. 

有关编译器优化的更完整信息,请参阅优化通知