Last active
June 5, 2019 20:54
-
-
Save thestonefox/cf27a10e0a2ba256881a809951b5f0cb to your computer and use it in GitHub Desktop.
A basic implementation of a laser pointer for the HTC Vive controllers in Unity3D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class ViveCursor : MonoBehaviour { | |
public enum AxisType | |
{ | |
XAxis, | |
ZAxis | |
} | |
public Color color; | |
public float thickness = 0.002f; | |
public AxisType facingAxis = AxisType.XAxis; | |
public float length = 100f; | |
public bool showCursor = true; | |
GameObject holder; | |
GameObject pointer; | |
GameObject cursor; | |
Vector3 cursorScale = new Vector3(0.05f, 0.05f, 0.05f); | |
float contactDistance = 0f; | |
Transform contactTarget = null; | |
void SetPointerTransform(float setLength, float setThicknes) | |
{ | |
//if the additional decimal isn't added then the beam position glitches | |
float beamPosition = setLength / (2 + 0.00001f); | |
if (facingAxis == AxisType.XAxis) | |
{ | |
pointer.transform.localScale = new Vector3(setLength, setThicknes, setThicknes); | |
pointer.transform.localPosition = new Vector3(beamPosition, 0f, 0f); | |
if (showCursor) | |
{ | |
cursor.transform.localPosition = new Vector3(setLength - cursor.transform.localScale.x, 0f, 0f); | |
} | |
} else | |
{ | |
pointer.transform.localScale = new Vector3(setThicknes, setThicknes, setLength); | |
pointer.transform.localPosition = new Vector3(0f, 0f, beamPosition); | |
if (showCursor) | |
{ | |
cursor.transform.localPosition = new Vector3(0f, 0f, setLength - cursor.transform.localScale.z); | |
} | |
} | |
} | |
// Use this for initialization | |
void Start () { | |
Material newMaterial = new Material(Shader.Find("Unlit/Color")); | |
newMaterial.SetColor("_Color", color); | |
holder = new GameObject(); | |
holder.transform.parent = this.transform; | |
holder.transform.localPosition = Vector3.zero; | |
pointer = GameObject.CreatePrimitive(PrimitiveType.Cube); | |
pointer.transform.parent = holder.transform; | |
pointer.GetComponent<MeshRenderer>().material = newMaterial; | |
pointer.GetComponent<BoxCollider>().isTrigger = true; | |
pointer.AddComponent<Rigidbody>().isKinematic = true; | |
pointer.layer = 2; | |
if (showCursor) | |
{ | |
cursor = GameObject.CreatePrimitive(PrimitiveType.Sphere); | |
cursor.transform.parent = holder.transform; | |
cursor.GetComponent<MeshRenderer>().material = newMaterial; | |
cursor.transform.localScale = cursorScale; | |
cursor.GetComponent<SphereCollider>().isTrigger = true; | |
cursor.AddComponent<Rigidbody>().isKinematic = true; | |
cursor.layer = 2; | |
} | |
SetPointerTransform(length, thickness); | |
} | |
float GetBeamLength(bool bHit, RaycastHit hit) | |
{ | |
float actualLength = length; | |
//reset if beam not hitting or hitting new target | |
if (!bHit || (contactTarget && contactTarget != hit.transform)) | |
{ | |
contactDistance = 0f; | |
contactTarget = null; | |
} | |
//check if beam has hit a new target | |
if (bHit) | |
{ | |
if (hit.distance <= 0) | |
{ | |
} | |
contactDistance = hit.distance; | |
contactTarget = hit.transform; | |
} | |
//adjust beam length if something is blocking it | |
if (bHit && contactDistance < length) | |
{ | |
actualLength = contactDistance; | |
} | |
if (actualLength <= 0) | |
{ | |
actualLength = length; | |
} | |
return actualLength; ; | |
} | |
void Update () { | |
Ray raycast = new Ray(transform.position, transform.forward); | |
RaycastHit hitObject; | |
bool rayHit = Physics.Raycast(raycast, out hitObject); | |
float beamLength = GetBeamLength(rayHit, hitObject); | |
SetPointerTransform(beamLength, thickness); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment