Unity HTC Vive realizes that the object is triggered by the handle, and the method is displayed in the direction the user is facing

In the project of VR virtual scene construction, it is necessary to realize the effect of partial enlargement of three-dimensional objects, to display the introduction function of different components, and to facilitate observation.

I imagine touching the target object through the handle, pulling the trigger to trigger the event, the target object is enlarged, other parts are hidden, and the rendering is turned off. Pull the trigger on the enlarged object and the object returns to its original state. At the same time, when the object is enlarged, no matter where the user is, the object is displayed in the direction of the user's realization orientation, that is, in front of the user.

Write a script, inherit the VRTK_InteractableObject class (the script used to control the interaction between the handle and the object in the steamVR plug-in VRTK).

Set parameters, such as the height after moving, the distance in front of the camera Rig position, the scale size after moving, the time for moving, etc.

To enumerate the state of the object, I set three idle moving placed

	// floor status
	private enum State { IDLE, MOVING, PLACED }

In the process of moving, the effects of moving, initial state idle, and zooming after moving are placed.

Define a variable, the IDLE state at the beginning, and record the initial position originPosition of the object at the beginning. Pivot difference. HMD data, etc.

	void Start(){
		state = State.IDLE;
		originPosition = transform.position;
		pivot = new Vector3 (0, Pivot, 0);
		scaleDelta = new Vector3 (Scale, Scale, Scale) / SpeedFrame;
		headset = VRTK_DeviceFinder.HeadsetTransform ();
	}

VRTK_DeviceFinder class: used to take photos of left and right handles, head-mounted display, return hardware number, location information, etc. in the scene.

In addition to HeadsetTransform, etc., other important APIs:

Get the game objects of the left and right controllers

VRTK_DeviceFinder.GetControllerRightHand();
VRTK_DeviceFinder.GetControllerLiftHand();

hu'o Get the hardware number corresponding to the left and right handles

VRTK_DeviceFinder.GetControllerIndex(rightHand)


Inherit the VRTK_InteractableObject class, refactor the StartUsing method, and press Trigger to perform state transition

public override void StartUsing(GameObject currentUsingObject) {
		base.StartUsing(currentUsingObject);
		switch (state) {
		case State.IDLE: {
				StartCoroutine(moveToPlayArea());
			}
			break;
		case State.MOVING:
			break;
		case State.PLACED: {
				StartCoroutine(moveBack());
			}
			break;
		}
	}

Move an object in front of the user:

private IEnumerator moveToPlayArea() {
		foreach (ModelInteractableObject o in models) {
			if (o.state == State.PLACED) {
				StartCoroutine (o.moveBack ());
			} else if (o.state == State.MOVING) {
				yield return new WaitWhile(() => o.state == State.MOVING);
			}
		}
		state = State.MOVING;
		Vector3 position = headset.position;
		position.y = Height;
		position += new Vector3(headset.forward.x, 0, headset.forward.z) * Distance;
		Vector3 dirDelta = (position - (transform.position + pivot)) / SpeedFrame;
		for(int i = 0; i < SpeedFrame; i++) {
			transform.Translate (dirDelta , Space.World);
			transform.localScale -= scaleDelta;
			yield return new WaitForEndOfFrame();
		}
		
		state = State.PLACED;
	}

The transformation of the three states of the object determines the position of the object's movement according to the position of the head-mounted display. Height, distance variable control. speedFrame controls time. Move by the Translate method.

Move the object back to its original position:

private IEnumerator moveBack() {
		state = State.MOVING;
		Vector3 dirDelta = (originPosition - transform.position) / SpeedFrame;
		for(int i = 0; i < SpeedFrame; i++) {
			transform.Translate (dirDelta , Space.World);
			transform.localScale += scaleDelta;
			yield return new WaitForEndOfFrame();
		}
		state = State.IDLE;
	}

Same as above method.


Source code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
using VRTK.Highlighters;

public class ModelInteractableObject : VRTK_InteractableObject {

	[Header("Model Interactable Object")]

	[Tooltip("Move the distance in front of")]
	public float Distance = 3f;
	[Tooltip("Move the height in front of")]
	public float Height = 1f;
	[Tooltip("Move the Scale in front of")]
	public float Scale = 0.5f;
	[Tooltip("Time to move to the target position, in frames")]
	public float SpeedFrame = 30.0f;
	[Tooltip("Pivot difference")]
	public float Pivot = 0;
	[Tooltip("FloorInfoPanel is used to display floor information")]
	public ModelInfoPanel FloorInfoPanel;
	[Tooltip("Information displayed in FloorInfoPanel")]
	public string Info;

	private enum State { IDLE, MOVING, PLACED }

	private State state;
	private Vector3 originPosition;
	private Vector3 pivot;
	private Vector3 scaleDelta;
	private Transform headset;

	private GameObject textPanel;

	private static ModelInteractableObject[] _models;
	private static ModelInteractableObject[] models {
		get {
			if (_models == null) {
				_models = FindObjectsOfType<ModelInteractableObject> ();
			}
			return _models;
		}
	}

	void Start(){
		state = State.IDLE;
		originPosition = transform.position;
		pivot = new Vector3 (0, Pivot, 0);
		scaleDelta = new Vector3 (Scale, Scale, Scale) / SpeedFrame;
		headset = VRTK_DeviceFinder.HeadsetTransform ();
	}

	// State transition when Trigger is pressed
	public override void StartUsing(GameObject currentUsingObject) {
		base.StartUsing(currentUsingObject);
		switch (state) {
		case State.IDLE: {
				StartCoroutine(moveToPlayArea());
			}
			break;
		case State.MOVING:
			break;
		case State.PLACED: {
				StartCoroutine(moveBack());
			}
			break;
		}
	}

	// turn on highlight on touch
	public override void OnInteractableObjectTouched (InteractableObjectEventArgs e) {
		if (state == State.PLACED || state == State.MOVING) {
			ToggleHighlight (false);
		}
		base.OnInteractableObjectTouched (e);
	}

	//Start touch, display handle highlight and Tooltips
	public override void StartTouching (GameObject currentTouchingObject) {
		base.StartTouching (currentTouchingObject);
		VRTK_ControllerActions action = currentTouchingObject.GetComponent<VRTK_ControllerActions> ();
		action.ToggleHighlightTrigger (true, Color.yellow);
		action.SetControllerOpacity (0.5f);
	}

	//Stop touch, turn off handle highlighting and Tooltips
	public override void StopTouching (GameObject previousTouchingObject) {
		base.StopTouching (previousTouchingObject);
		///FloorInfoPanel.gameObject.SetActive (false);

		VRTK_ControllerActions action = previousTouchingObject.GetComponent<VRTK_ControllerActions> ();
		action.ToggleHighlightTrigger (false);
		action.SetControllerOpacity (1f);
	}

	private IEnumerator moveToPlayArea() {
		foreach (ModelInteractableObject o in models) {
			if (o.state == State.PLACED) {
				StartCoroutine (o.moveBack ());
			} else if (o.state == State.MOVING) {
				yield return new WaitWhile(() => o.state == State.MOVING);
			}
		}
		state = State.MOVING;
		Vector3 position = headset.position;
		position.y = Height;
		position += new Vector3(headset.forward.x, 0, headset.forward.z) * Distance;
		Vector3 dirDelta = (position - (transform.position + pivot)) / SpeedFrame;
		for(int i = 0; i < SpeedFrame; i++) {
			transform.Translate (dirDelta , Space.World);
			transform.localScale -= scaleDelta;
			yield return new WaitForEndOfFrame();
		}
		state = State.PLACED;
	}

	private IEnumerator moveBack() {
		state = State.MOVING;
		Vector3 dirDelta = (originPosition - transform.position) / SpeedFrame;
		for(int i = 0; i < SpeedFrame; i++) {
			transform.Translate (dirDelta , Space.World);
			transform.localScale += scaleDelta;
			yield return new WaitForEndOfFrame();
		}
		state = State.IDLE;
	}
}





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324777252&siteId=291194637