在开发VR过程中 UI点击用射线检测,改写了SteamVR_LaserPointer类。 目标实现 PointerIn,PointerOut,ClickedDown,Clicking,ClickedUp。 用的是手柄的Trigger
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
// Made by LCX
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121
using UnityEngine;
using System.Collections;
public struct PointerEventArgs
{
public uint controllerIndex;
public uint flags;
public float distance;
public Transform target;
}
public delegate void PointerEventHandler(object sender, PointerEventArgs e);
public class SteamVR_LaserPointer : MonoBehaviour
{
public bool active = true;
public Color color;
public float thickness = 0.002f;
[HideInInspector] public GameObject holder;
[HideInInspector] public GameObject pointer;
private bool isActive = false;
public bool addRigidBody = false;
public Transform reference;
public event PointerEventHandler PointerIn;
public event PointerEventHandler PointerOut;
public event PointerEventHandler ClickedDown;
public event PointerEventHandler Clicking;
public event PointerEventHandler ClickedUp;
public static SteamVR_LaserPointer Instance;
public Material LaserMaterial;
private Transform previousContact = null;
// Use this for initialization
private SteamVR_TrackedObject _steamVrTrackedObject;
#region 初始化
private void Start()
{
Instance = this;
controller = GetComponent();
holder = new GameObject();
holder.transform.parent = this.transform;
holder.transform.localPosition = Vector3.zero;
holder.transform.localRotation = Quaternion.identity;
_steamVrTrackedObject = GetComponent();
pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
pointer.transform.parent = holder.transform;
pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
pointer.transform.localPosition = new Vector3(0f, 0f, 50f);
pointer.transform.localRotation = Quaternion.identity;
BoxCollider collider = pointer.GetComponent();
if (addRigidBody)
{
if (collider)
{
collider.isTrigger = true;
}
Rigidbody rigidBody = pointer.AddComponent();
rigidBody.isKinematic = true;
}
else
{
if (collider)
{
Object.Destroy(collider);
}
}
if (LaserMaterial == null)
{
LaserMaterial = new Material(Shader.Find("Unlit/Color"));
LaserMaterial.SetColor("_Color", color);
}
pointer.GetComponent().material = LaserMaterial;
}
#endregion
#region
public virtual void OnPointerIn(PointerEventArgs e)
{
if (PointerIn != null)
PointerIn(this, e);
var ui = e.target.GetComponent();
if (ui != null)
{
ui.OnPointIn();
}
}
public virtual void OnPointerOut(PointerEventArgs e)
{
if (PointerOut != null)
PointerOut(this, e);
var ui = e.target.GetComponent();
if (ui != null)
{
ui.OnPointOut();
}
}
public virtual void OnClickDown(PointerEventArgs e)
{
if (ClickedDown != null)
ClickedDown(this, e);
var ui = e.target.GetComponent();
if (ui != null)
{
ui.OnClickedDown();
}
}
public virtual void OnClickUp(PointerEventArgs e)
{
if (ClickedUp != null)
ClickedUp(this, e);
var ui = e.target.GetComponent();
if (ui != null)
{
ui.OnClickedUp();
}
}
public virtual void OnClick(PointerEventArgs e)
{
if (Clicking != null)
Clicking(this, e);
var ui = e.target.GetComponent();
if (ui != null)
{
ui.OnClicking();
}
}
#endregion
private SteamVR_TrackedController controller;
private float dist = 100f;
private RaycastHit hit;
// Update is called once per frame
private void Update()
{
var device = SteamVR_Controller.Input((int)_steamVrTrackedObject.index);
if (!isActive)
{
isActive = true;
this.transform.GetChild(0).gameObject.SetActive(true);
}
Ray raycast = new Ray(transform.position, transform.forward);
bool bHit = Physics.Raycast(raycast, out hit);
if (previousContact && previousContact != hit.transform)
{
PointerEventArgs args = new PointerEventArgs();
if (controller != null)
{
args.controllerIndex = controller.controllerIndex;
}
args.distance = 0f;
args.flags = 0;
args.target = previousContact;
OnPointerOut(args);
previousContact = null;
}
if (bHit && previousContact != hit.transform)
{
PointerEventArgs argsIn = new PointerEventArgs();
if (controller != null)
{
argsIn.controllerIndex = controller.controllerIndex;
}
argsIn.distance = hit.distance;
argsIn.flags = 0;
argsIn.target = hit.transform;
OnPointerIn(argsIn);
previousContact = hit.transform;
}
if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger)&& bHit)
{
PointerEventArgs argsIn = new PointerEventArgs();
if (controller != null)
{
argsIn.controllerIndex = controller.controllerIndex;
}
argsIn.distance = hit.distance;
argsIn.flags = 0;
argsIn.target = hit.transform;
OnClickDown(argsIn);
previousContact = hit.transform;
}
if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger) && bHit)
{
PointerEventArgs argsIn = new PointerEventArgs();
if (controller != null)
{
argsIn.controllerIndex = controller.controllerIndex;
}
argsIn.distance = hit.distance;
argsIn.flags = 0;
argsIn.target = hit.transform;
OnClickUp(argsIn);
previousContact = hit.transform;
}
//TODO
if (device.GetPress(SteamVR_Controller.ButtonMask.Trigger) && bHit)
{
PointerEventArgs argsIn = new PointerEventArgs();
if (controller != null)
{
argsIn.controllerIndex = controller.controllerIndex;
}
argsIn.distance = hit.distance;
argsIn.flags = 0;
argsIn.target = hit.transform;
OnClick(argsIn);
previousContact = hit.transform;
}
if (!bHit)
{
previousContact = null;
}
if (bHit && hit.distance < 100f)
{
dist = hit.distance;
}
if (controller != null && controller.triggerPressed)
{
pointer.transform.localScale = new Vector3(thickness*5f, thickness*5f, dist);
}
else
{
pointer.transform.localScale = new Vector3(thickness, thickness, dist);
}
pointer.transform.localPosition = new Vector3(0f, 0f, dist/2f);
}
}
// Made by LCX
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121
public interface IVRUI
{
void OnPointIn();
void OnPointOut();
void OnClickedDown();
void OnClickedUp();
void OnClicking();
}
// Made by LCX
// This FrameWork includes some tools and modules which are used usually. Feel free to contact with us at ant time.Thanks
// QQ: 594721121
using System;
using UnityEngine;
public abstract class VRUIBase : MonoBehaviour,IVRUI
{
public event Action OnInUi;
public event Action OnOutUi;
public event Action OnTriggerDownUi;
public event Action OnTriggerUpUi;
public event Action OnTriggerUi;
public virtual void OnDestroy()
{
OnInUi = null;
OnOutUi = null;
OnTriggerDownUi = null;
OnTriggerUpUi = null;
OnTriggerUi = null;
}
public void OnPointIn()
{
if (OnInUi!=null)OnInUi();
}
public void OnPointOut()
{
if (OnOutUi != null)OnOutUi();
}
public void OnClickedDown()
{
if (OnTriggerDownUi != null) OnTriggerDownUi();
}
public void OnClickedUp()
{
if (OnTriggerUpUi != null) OnTriggerUpUi();
}
public void OnClicking()
{
if (OnTriggerUi != null) OnTriggerUi();
}
}
UI 元素挂上 VRUIBase 添加collider。 即可调用