Skip to content

Commit

Permalink
feat(Locomotion): add snap rotation touchpad control action
Browse files Browse the repository at this point in the history
A new touchpad control action has been added that causes the controlled
object to snap rotate around it's `up` vector based on the position of
the touchpad axis.

This provides a sudden change in rotation angle as opposed to the
smooth angle change of the Rotate touchpad control action.

It's also possible to provide a delay between each rotation and an
optional fade/blink between each rotation to reduce nausia.

This can be useful for rotating the play area for seated games.
  • Loading branch information
thestonefox committed Feb 1, 2017
1 parent 8b0a80b commit c2669b0
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Snap Rotate Touchpad Control Action|TouchpadControlActions|25030
namespace VRTK
{
using UnityEngine;

/// <summary>
/// The Snap Rotate Touchpad Control Action script is used to snap rotate the controlled GameObject around the up vector when changing the touchpad axis.
/// </summary>
/// <remarks>
/// The effect is a immediate snap rotation to quickly face in a new direction.
/// </remarks>
public class VRTK_SnapRotateTouchpadControlAction : VRTK_BaseTouchpadControlAction
{
[Tooltip("The angle to rotate for each snap.")]
public float anglePerSnap = 30f;
[Tooltip("The snap angle multiplier to be applied when the modifier button is pressed.")]
public float angleMultiplier = 1.5f;
[Tooltip("The amount of time required to pass before another snap rotation can be carried out.")]
public float snapDelay = 0.5f;
[Tooltip("The speed for the headset to fade out and back in. Having a blink between rotations can reduce nausia.")]
public float blinkTransitionSpeed = 0.6f;

private Collider centerCollider;
private Transform controlledTransform;
private Transform playArea;
private float snapDelayTimer = 0f;

/// <summary>
/// The ProcessFixedUpdate method is run for every FixedUpdate on the Touchpad Control script.
/// </summary>
/// <param name="controlledGameObject">The GameObject that is going to be affected.</param>
/// <param name="directionDevice">The device that is used for the direction.</param>
/// <param name="axisDirection">The axis that is being affected from the touchpad.</param>
/// <param name="axis">The value of the current touchpad touch point based across the axis direction.</param>
/// <param name="deadzone">The value of the deadzone based across the axis direction.</param>
/// <param name="currentlyFalling">Whether the controlled GameObject is currently falling.</param>
/// <param name="modifierActive">Whether the modifier button is pressed.</param>
public override void ProcessFixedUpdate(GameObject controlledGameObject, Transform directionDevice, Vector3 axisDirection, float axis, float deadzone, bool currentlyFalling, bool modifierActive)
{
if (snapDelayTimer < Time.timeSinceLevelLoad)
{
float angle = Rotate(axis, modifierActive);
if (angle != 0f)
{
Blink();
RotateAroundPlayer(controlledGameObject, angle);
}
}
}

protected virtual void OnEnable()
{
playArea = VRTK_DeviceFinder.PlayAreaTransform();
}

protected virtual void RotateAroundPlayer(GameObject controlledGameObject, float angle)
{
Vector3 objectCenter = GetObjectCenter(controlledGameObject.transform);
Vector3 objectPosition = controlledGameObject.transform.TransformPoint(objectCenter);
controlledGameObject.transform.Rotate(Vector3.up, angle);
objectPosition -= controlledGameObject.transform.TransformPoint(objectCenter);
controlledGameObject.transform.position += objectPosition;
}

protected virtual float Rotate(float axis, bool modifierActive)
{
snapDelayTimer = Time.timeSinceLevelLoad + snapDelay;
int axisDirection = 0;
if (axis < 0)
{
axisDirection = -1;
}
else if (axis > 0)
{
axisDirection = 1;
}
return (anglePerSnap * (modifierActive ? angleMultiplier : 1)) * axisDirection;
}

protected virtual void Blink()
{
if (blinkTransitionSpeed > 0f)
{
VRTK_SDK_Bridge.HeadsetFade(Color.black, 0);
Invoke("ReleaseBlink", 0.01f);
}
}

protected virtual void ReleaseBlink()
{
VRTK_SDK_Bridge.HeadsetFade(Color.clear, blinkTransitionSpeed);
}

protected virtual Vector3 GetObjectCenter(Transform checkObject)
{
if (centerCollider == null || checkObject != controlledTransform)
{
controlledTransform = checkObject;

if (checkObject == playArea)
{
CapsuleCollider playAreaCollider = playArea.GetComponent<CapsuleCollider>();
centerCollider = playAreaCollider;
return playAreaCollider.center;
}
else
{
centerCollider = checkObject.GetComponent<Collider>();
}
}

return Vector3.zero;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Assets/VRTK/Scripts/Locomotion/VRTK_TouchpadControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,22 @@ protected virtual void FixedUpdate()
CheckDirectionDevice();
CheckFalling();
ModifierButtonActive();
if (xAxisActionScript && xAxisActionScript.enabled)
if (xAxisActionScript && xAxisActionScript.enabled && OutsideDeadzone(touchpadAxis.x, axisDeadzone.x))
{
xAxisActionScript.ProcessFixedUpdate(controlledGameObject, directionDevice, directionDevice.right, touchpadAxis.x, axisDeadzone.x, currentlyFalling, modifierActive);
}

if (yAxisActionScript && yAxisActionScript.enabled)
if (yAxisActionScript && yAxisActionScript.enabled && OutsideDeadzone(touchpadAxis.y, axisDeadzone.y))
{
yAxisActionScript.ProcessFixedUpdate(controlledGameObject, directionDevice, directionDevice.forward, touchpadAxis.y, axisDeadzone.y, currentlyFalling, modifierActive);
}
}

protected virtual bool OutsideDeadzone(float axisValue, float deadzoneThreshold)
{
return (axisValue > deadzoneThreshold || axisValue < -deadzoneThreshold);
}

protected virtual void CheckSetupControlAction()
{
if (xAxisActionScript && yAxisActionScript && xAxisActionScript.GetInstanceID() == yAxisActionScript.GetInstanceID())
Expand Down
38 changes: 38 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@ This directory contains scripts that are used to provide different actions when
* [Base Touchpad Control Action](#base-touchpad-control-action-vrtk_basetouchpadcontrolaction)
* [Slide Touchpad Control Action](#slide-touchpad-control-action-vrtk_slidetouchpadcontrolaction)
* [Rotate Touchpad Control Action](#rotate-touchpad-control-action-vrtk_rotatetouchpadcontrolaction)
* [Snap Rotate Touchpad Control Action](#snap-rotate-touchpad-control-action-vrtk_snaprotatetouchpadcontrolaction)

---

Expand Down Expand Up @@ -1393,6 +1394,43 @@ The ProcessFixedUpdate method is run for every FixedUpdate on the Touchpad Contr

---

## Snap Rotate Touchpad Control Action (VRTK_SnapRotateTouchpadControlAction)
> extends [VRTK_BaseTouchpadControlAction](#base-touchpad-control-action-vrtk_basetouchpadcontrolaction)

### Overview

The Snap Rotate Touchpad Control Action script is used to snap rotate the controlled GameObject around the up vector when changing the touchpad axis.

The effect is a immediate snap rotation to quickly face in a new direction.

### Inspector Parameters

* **Angle Per Snap:** The angle to rotate for each snap.
* **Angle Multiplier:** The snap angle multiplier to be applied when the modifier button is pressed.
* **Snap Delay:** The amount of time required to pass before another snap rotation can be carried out.
* **Blink Transition Speed:** The speed for the headset to fade out and back in. Having a blink between rotations can reduce nausia.

### Class Methods

#### ProcessFixedUpdate/7

> `public override void ProcessFixedUpdate(GameObject controlledGameObject, Transform directionDevice, Vector3 axisDirection, float axis, float deadzone, bool currentlyFalling, bool modifierActive)`

* Parameters
* `GameObject controlledGameObject` - The GameObject that is going to be affected.
* `Transform directionDevice` - The device that is used for the direction.
* `Vector3 axisDirection` - The axis that is being affected from the touchpad.
* `float axis` - The value of the current touchpad touch point based across the axis direction.
* `float deadzone` - The value of the deadzone based across the axis direction.
* `bool currentlyFalling` - Whether the controlled GameObject is currently falling.
* `bool modifierActive` - Whether the modifier button is pressed.
* Returns
* _none_

The ProcessFixedUpdate method is run for every FixedUpdate on the Touchpad Control script.

---

# Interactions (VRTK/Scripts/Interactions)

A collection of scripts that provide the ability to interact with game objects with the controllers.
Expand Down

0 comments on commit c2669b0

Please sign in to comment.