Adventure Creator Wikia
Advertisement

This script allows you to interact with a menu using VR controllers.

  1. Create a menu that uses Unity UI as its Source, and set its Canvas to act in World Space.
  2. For each Button in contains, attach a Box Collider that covers it.
  3. Copy/paste the script below into a C# script named TouchUI.cs, and attach it to each of the VR rig's controllers (the objects with the Tracked Pose Driver component)
  4. Fill in the Touch UI Inspector, optionally assigning a Line Renderer to provide a line pointing from the controller.
  5. For each, assign a Trigger Input Axis name, and define this name in Unity's Input Manager. Give the input a positive button of "joystick button 14" and "joystick button 15" for LeftTrigger / RightTrigger respectively.

TouchUI.cs:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class TouchUI : MonoBehaviour
{

	#region Variables

	[Header ("Input")]
	[SerializeField] public LayerMask layerMask = new LayerMask ();
	[SerializeField] private string triggerInputAxis;

	[Header ("Visual")]
	[SerializeField] LineRenderer lineRenderer = null;
	[SerializeField] private Color lineSelectColor = Color.white;
	[SerializeField] private Color lineDeselectColor = Color.grey;
	[SerializeField] private float lineWidth = 0.06f;

	private Vector3[] points;
	private Selectable selectable;
	private bool waitForTriggerRelease;

	#endregion


	#region UnityStandards

	private void Start ()
	{
		points = new Vector3[2];
		points[0] = Vector3.zero;
		points[1] = transform.position + new Vector3 (0, 0, 20);

		if (lineRenderer)
		{
			lineRenderer.startWidth = lineWidth;
			lineRenderer.endWidth = lineWidth;
			lineRenderer.SetPositions (points);
			lineRenderer.enabled = true;
		}
	}


	private void Update ()
	{
		AlignLineRenderer ();
		DetectClicks ();
	}

	#endregion


	#region PrivateFunctions

	private void AlignLineRenderer ()
	{
		Ray ray = new Ray (transform.position, transform.forward);
		RaycastHit hit;

		if (Physics.Raycast (ray, out hit, layerMask))
		{
			points[1] = transform.forward + new Vector3 (0, 0, hit.distance);

			if (lineRenderer)
			{
				lineRenderer.startColor = lineSelectColor;
				lineRenderer.endColor = lineSelectColor;
			}

			selectable = hit.collider.gameObject.GetComponent<Selectable> ();
			if (selectable)
			{
				selectable.Select ();
			}
		}
		else
		{
			points[1] = transform.forward + new Vector3 (0, 0, 20);

			if (lineRenderer)
			{
				lineRenderer.startColor = lineDeselectColor;
				lineRenderer.endColor = lineDeselectColor;
			}

			if (selectable)
			{
				if (EventSystem.current.currentSelectedGameObject && EventSystem.current.currentSelectedGameObject == selectable.gameObject)
				{
					EventSystem.current.SetSelectedGameObject (null);
				}

				selectable = null;
			}
		}

		if (lineRenderer)
		{
			lineRenderer.SetPositions (points);
			lineRenderer.material.color = lineRenderer.startColor;
		}
	}


	private void DetectClicks ()
	{
		if (Input.GetAxis (triggerInputAxis) > 0f)
		{
			if (waitForTriggerRelease)
			{
				return;
			}

			if (selectable)
			{
				Button button = selectable as Button;
				if (button)
				{
					button.onClick?.Invoke ();
				}

				waitForTriggerRelease = true;
			}
		}
		else
		{
			waitForTriggerRelease = false;
		}
	}

	#endregion

}
Advertisement