Skip to content

Instantly share code, notes, and snippets.

@mnstrspeed
Created April 26, 2017 01:49
Show Gist options
  • Save mnstrspeed/4d30d7f7efe3135265b64a9eef2ef86f to your computer and use it in GitHub Desktop.
Save mnstrspeed/4d30d7f7efe3135265b64a9eef2ef86f to your computer and use it in GitHub Desktop.
Implementation of rectangular gain locomotion (originally described in this talk at Vision Summit 2016: https://www.youtube.com/watch?v=At_Zac4Xezw)
using UnityEngine;
public class RectangularGainLocomotion : MonoBehaviour
{
public Transform Head;
public float Gain = 1f;
public Vector2 NeutralAreaSize = Vector2.one;
[Header("Visual helpers")]
public Transform NeutralAreaPreview;
public Transform HeadFloorPreview;
private Vector2 halfNeutralAreaSize
{
get { return this.NeutralAreaSize * 0.5f; }
}
private Vector3 neutralAreaPosition;
void OnEnable()
{
this.neutralAreaPosition = this.transform.InverseTransformPoint(this.Head.position);
this.neutralAreaPosition.y = 0f;
this.HeadFloorPreview.gameObject.SetActive(true);
this.NeutralAreaPreview.gameObject.SetActive(true);
this.NeutralAreaPreview.localScale = new Vector3(this.NeutralAreaSize.x, 1, this.NeutralAreaSize.y);
}
void OnDisable()
{
this.HeadFloorPreview.gameObject.SetActive(false);
this.NeutralAreaPreview.gameObject.SetActive(false);
}
void Update()
{
Vector3 localPlayerPosition = this.transform.InverseTransformPoint(this.Head.position);
Vector3 floorPosition = new Vector3(localPlayerPosition.x, 0f, localPlayerPosition.z);
Vector3 positionInNeutralZone = floorPosition - this.neutralAreaPosition;
if (Mathf.Abs(positionInNeutralZone.x) > this.halfNeutralAreaSize.x)
{
this.neutralAreaPosition.x +=
Mathf.Sign(positionInNeutralZone.x) * Mathf.Abs(Mathf.Abs(positionInNeutralZone.x) - this.halfNeutralAreaSize.x);
}
if (Mathf.Abs(positionInNeutralZone.z) > this.halfNeutralAreaSize.y)
{
this.neutralAreaPosition.z +=
Mathf.Sign(positionInNeutralZone.z) * Mathf.Abs(Mathf.Abs(positionInNeutralZone.z) - this.halfNeutralAreaSize.y);
}
this.transform.localPosition = this.Gain * this.neutralAreaPosition;
this.NeutralAreaPreview.localPosition = this.neutralAreaPosition;
this.HeadFloorPreview.localPosition = floorPosition;
}
#region Debug visualization
void OnDrawGizmos()
{
if (!this.isActiveAndEnabled)
return;
this.DrawNeutralAreaDebug();
var playArea = this.GetComponent<SteamVR_PlayArea>();
if (playArea != null)
{
Gizmos.color = Color.green;
this.DrawWireframe(playArea.vertices);
}
}
private void DrawWireframe(Vector3[] vertices)
{
if (vertices == null || vertices.Length == 0)
return;
var offset = transform.TransformVector(Vector3.up * 2f);
for (int i = 0; i < 4; i++)
{
int next = (i + 1) % 4;
var a = vertices[i] + new Vector3(
vertices[i].x - Mathf.Sign(vertices[i].x) * this.halfNeutralAreaSize.x, 0,
vertices[i].z - Mathf.Sign(vertices[i].z) * this.halfNeutralAreaSize.y) * this.Gain;
var b = a + offset;
var c = vertices[next] + new Vector3(
vertices[next].x - Mathf.Sign(vertices[next].x) * this.halfNeutralAreaSize.x, 0,
vertices[next].z - Mathf.Sign(vertices[next].z) * this.halfNeutralAreaSize.y) * this.Gain;
var d = c + offset;
Gizmos.DrawLine(a, b);
Gizmos.DrawLine(a, c);
Gizmos.DrawLine(b, d);
}
}
private void DrawNeutralAreaDebug()
{
Vector3[] vertices = new Vector3[]
{
this.neutralAreaPosition + new Vector3(-this.halfNeutralAreaSize.x, 0, this.halfNeutralAreaSize.y),
this.neutralAreaPosition + new Vector3(this.halfNeutralAreaSize.x, 0, this.halfNeutralAreaSize.y),
this.neutralAreaPosition + new Vector3(this.halfNeutralAreaSize.x, 0, -this.halfNeutralAreaSize.y),
this.neutralAreaPosition + new Vector3(-this.halfNeutralAreaSize.x, 0, -this.halfNeutralAreaSize.y),
};
for (int i = 0; i < vertices.Length; i++)
{
Vector3 p1 = this.transform.TransformPoint(vertices[i]);
Vector3 p2 = this.transform.TransformPoint(vertices[(i + 1) % vertices.Length]);
Debug.DrawLine(p1, p2);
}
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment