刚开始先查看了其他道友的方案:1.Unity使用SteamVR2.0实现基本功能(瞬移,抓取物品,射线点击,UI交互等)_贪小心的博客-CSDN博客_unity steam vr
2.【Steam VR 2.0】5.射线操作UGUI-射线点击物体_恩博同学的博客-CSDN博客_htc steamvr 射线点击ui
嗯。。。试着尝试了一下,不是很好用,于是乎记得以前用过得的方法(别人做的,我只是使用者),剔除出来,整理一下。
一 UGUI射线点击:
使用插件:CurvedUI(CurvedUI+DOTween+Shaders+Sprites-其它文档类资源-CSDN文库),SteamVR Plugin(商店免费)
场景使用SteamVR 的Interactions_Example场景测试的
1.将CurvedUI 下的CurvedUILaserPointer预制体 放置 SteamVR的 Player 下。
其他设置
二 物品射线点击:
继承重写类:CurvedUILaserBeam
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;
using Valve.VR;
using Valve.VR.Extras;
using UnityEngine.Events;
namespace CurvedUI
{
///
/// This class contains code that controls the visuals (only!) of the laser pointer.
///
public class CurvedUILaserBeam : MonoBehaviour
{
public SteamVR_Action_Boolean interactWithModel = SteamVR_Input.GetBooleanAction("GrabPinch");
bool isActive = false;
public event PointerEventHandler PointerClickModel;
Transform previousContact = null;
public virtual void OnPointerClickModel(PointerEventArgs e)
{
if (PointerClickModel != null)
PointerClickModel(this, e);
}
GameObject itemObject = null;
bool bo = false;
#pragma warning disable 0649
[SerializeField]
Transform LaserBeamTransform;
[SerializeField]
Transform LaserBeamDot;
[SerializeField]
bool hideWhenNotAimingAtCanvas = false;
#pragma warning restore 0649
protected void Update()
{
//get direction of the controller
Ray myRay = new Ray(this.transform.position, this.transform.forward);
//make laser beam hit stuff it points at.
if (LaserBeamTransform && LaserBeamDot)
{
float length = 10000;
RaycastHit hit;
if (Physics.Raycast(myRay, out hit, length, CurvedUIInputModule.Instance.RaycastLayerMask))
{
length = Vector3.Distance(hit.point, this.transform.position);
CurvedUISettings cuiSettings = hit.collider.GetComponentInParent();
if (cuiSettings != null)//UI 界面
{
// Debug.Log("是 UI 界面");
//find if there are any canvas objects we're pointing at. we only want transforms with graphics to block the pointer. (that are drawn by canvas => depth not -1)
int selectablesUnderPointer = cuiSettings.GetObjectsUnderPointer().FindAll(x =>
x != null && x.GetComponent() != null && x.GetComponent().depth != -1).Count;
length = selectablesUnderPointer == 0
? 10000
: Vector3.Distance(hit.point, this.transform.position);
}
else{ length = 0; }
}
else if (Physics.Raycast(myRay, out hit, length, LayerMask.GetMask("Obj")))
{
//物品的 Layer 设置 Obj ,挂载组件:BoxCollider,FT_InteractableRay
length = Vector3.Distance(hit.point, this.transform.position);
FT_InteractableRay FT_InteractableRay = hit.collider.GetComponentInParent();
BoxCollider boxCollider = hit.collider.GetComponentInParent();
if (boxCollider != null&& FT_InteractableRay != null)
{
length = 1000;
length = Vector3.Distance(hit.point, this.transform.position);
itemObject = hit.collider.gameObject;
if (!bo)
{
bo = true;
itemObject.GetComponent().RayEnter();
}
if (CurvedUIInputModule.Instance.SteamVRClickAction.GetStateDown(Valve.VR.SteamVR_Input_Sources.RightHand))
{
//点击
itemObject.GetComponent().RayClick();
}
else if (CurvedUIInputModule.Instance.SteamVRClickAction.GetStateDown(Valve.VR.SteamVR_Input_Sources.LeftHand))
{
//点击
itemObject.GetComponent().RayClick();
}
}
}
else
{
bo = false;
itemObject?.GetComponent().RayExit();
itemObject = null;
length = 0;
}
//set the leangth of the beam
LaserBeamTransform.localScale = LaserBeamTransform.localScale.ModifyZ(length);
射线长度为零的时候隐藏射线
//if (Math.Abs(length) < 0.0001f && LaserBeamTransform.gameObject.activeSelf)
// LaserBeamTransform.gameObject.SetActive(false);
//else if (Math.Abs(length) >= 0.0001f && !LaserBeamTransform.gameObject.activeSelf)
// LaserBeamTransform.gameObject.SetActive(true);
}
}
}
}
2.挂载物品上代码
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class FT_InteractableRay : MonoBehaviour
{
public bool isActive = true;
public UnityEvent OnRayEnter;
public UnityEvent OnRayExit;
public UnityEvent OnRayClick;
public virtual void RayEnter()
{
OnRayEnter?.Invoke();
// this.GetComponent().highlighted = false;
Debug.Log("射线进入:" + name);
}
public virtual void RayExit()
{
OnRayExit?.Invoke();
Debug.Log("射线离开:" + name);
}
public virtual void RayClick()
{
OnRayClick?.Invoke();
Debug.Log("射线点击:" + name);
}
}
3.逻辑测试 代码
using HighlightPlus;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
this.gameObject.GetComponent().OnRayEnter.AddListener(() => {
this.gameObject.GetComponent().highlighted = true;
});
this.gameObject.GetComponent().OnRayExit.AddListener(() => {
this.gameObject.GetComponent().highlighted = false;
});
this.gameObject.GetComponent().OnRayClick.AddListener(() => {
});
}
// Update is called once per frame
void Update()
{
}
}
完事!!!!!!!!!!!
后面 慢慢完善一下。
以上 方案我以弃用,不是不好用,而是 很多功能需要自己 集成。恰好找到了一个别人集成好的方案。
:Unity VR Interaction Framework+VIVE Cosmos(完美组合)_野区捕龙为宠的博客-CSDN博客