实现的一个功能##
大概实现的内容就是,扣动扳机的时候,如果指向一个在远处物体,那么可以吧远处的物体放到我们
边上一个离我们很近的位置.这样就实现了从远处获取物体的功能.
发射射线代码脚本展示:
明确事件的发布,相应与调用:
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;
public GameObject holder;
public GameObject pointer;
bool isActive = false;
public bool addRigidBody = false;
public Transform reference;
public event PointerEventHandler PointerIn;
public event PointerEventHandler PointerOut;
Transform previousContact = null;
// Use this for initialization
void Start ()
{
holder = new GameObject();
holder.transform.parent = this.transform;
holder.transform.localPosition = Vector3.zero;
holder.transform.localRotation = Quaternion.identity;
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);
}
}
Material newMaterial = new Material(Shader.Find("Unlit/Color"));
newMaterial.SetColor("_Color", color);
pointer.GetComponent().material = newMaterial;
}
public virtual void OnPointerIn(PointerEventArgs e)
{
if (PointerIn != null)
PointerIn(this, e);
}
public virtual void OnPointerOut(PointerEventArgs e)
{
if (PointerOut != null)
PointerOut(this, e);
}
// Update is called once per frame
void Update ()
{
if (!isActive)
{
isActive = true;
this.transform.GetChild(0).gameObject.SetActive(true);
}
float dist = 100f;
SteamVR_TrackedController controller = GetComponent();
Ray raycast = new Ray(transform.position, transform.forward);
RaycastHit hit;
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(!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);
}
}
自己逻辑代码展示:
public class TestCatchObj : MonoBehaviour {
SteamVR_LaserPointer pointer;//发射射线的脚本
SteamVR_TrackedController obj;//获取外部交互设备的脚本
Transform pointT;//一个用来承储Transoform的东西
GameObject currentCatch;//用来保留物体的变量
void Start () {
pointer = new SteamVR_LaserPointer();
pointer = GetComponent();//获取脚本
pointer.PointerIn += Pointer_PointerIn;//PointerIn,是脚本里面的事件变量
pointer.PointerOut += Pointer_PointerOut;//射线进入出去的两个方法
obj = GetComponent();//获取交互设备
obj.TriggerClicked += Obj_TriggerClicked;//交互设备的多个事件
obj.TriggerUnclicked += Obj_TriggerUnclicked;
}
private void Obj_TriggerUnclicked(object sender, ClickedEventArgs e)//扳机松开方法的执行
{
if (currentCatch==null)
{
return;
}
var device = SteamVR_Controller.Input((int)this.GetComponent().index);
device.TriggerHapticPulse(2800);
currentCatch.GetComponent().velocity = device.velocity * 5;
currentCatch.GetComponent().angularVelocity = device.angularVelocity;
Destroy(currentCatch.GetComponent());
currentCatch = null;
}
private void Obj_TriggerClicked(object sender, ClickedEventArgs e)//扳机按下方法的执行
{
if (pointer==null)
{
return;
}
pointT.gameObject.AddComponent().connectedBody = this.GetComponent();
currentCatch = pointT.gameObject;
}
private void Pointer_PointerOut(object sender, PointerEventArgs e)//射线出去的执行
{
pointT = null;
}
private void Pointer_PointerIn(object sender, PointerEventArgs e)//射线进入的执行
{
if (e.target.gameObject.tag=="Player")
{
pointT = e.target;
}
}
void Update () {
}
}
SteamVR_TrackedController 响应的事件系统
using UnityEngine;
using Valve.VR;
public struct ClickedEventArgs
{
public uint controllerIndex;
public uint flags;
public float padX, padY;
}
public delegate void ClickedEventHandler(object sender, ClickedEventArgs e);//委托
public class SteamVR_TrackedController : MonoBehaviour
{
public uint controllerIndex;
public VRControllerState_t controllerState;
public bool triggerPressed = false;
public bool steamPressed = false;
public bool menuPressed = false;
public bool padPressed = false;
public bool padTouched = false;
public bool gripped = false;
//事件
public event ClickedEventHandler MenuButtonClicked;
public event ClickedEventHandler MenuButtonUnclicked;
public event ClickedEventHandler TriggerClicked;
public event ClickedEventHandler TriggerUnclicked;
public event ClickedEventHandler SteamClicked;
public event ClickedEventHandler PadClicked;
public event ClickedEventHandler PadUnclicked;
public event ClickedEventHandler PadTouched;
public event ClickedEventHandler PadUntouched;
public event ClickedEventHandler Gripped;
public event ClickedEventHandler Ungripped;
// Use this for initialization
void Start()
{
if (this.GetComponent() == null)
{
gameObject.AddComponent();
}
if (controllerIndex != 0)
{
this.GetComponent().index = (SteamVR_TrackedObject.EIndex)controllerIndex;
if (this.GetComponent() != null)
{
this.GetComponent().index = (SteamVR_TrackedObject.EIndex)controllerIndex;
}
}
else
{
controllerIndex = (uint) this.GetComponent().index;
}
}
//重写的方法
public void SetDeviceIndex(int index)
{
this.controllerIndex = (uint) index;
}
public virtual void OnTriggerClicked(ClickedEventArgs e)
{
if (TriggerClicked != null)
TriggerClicked(this, e);
}
public virtual void OnTriggerUnclicked(ClickedEventArgs e)
{
if (TriggerUnclicked != null)
TriggerUnclicked(this, e);
}
public virtual void OnMenuClicked(ClickedEventArgs e)
{
if (MenuButtonClicked != null)
MenuButtonClicked(this, e);
}
public virtual void OnMenuUnclicked(ClickedEventArgs e)
{
if (MenuButtonUnclicked != null)
MenuButtonUnclicked(this, e);
}
public virtual void OnSteamClicked(ClickedEventArgs e)
{
if (SteamClicked != null)
SteamClicked(this, e);
}
public virtual void OnPadClicked(ClickedEventArgs e)
{
if (PadClicked != null)
PadClicked(this, e);
}
public virtual void OnPadUnclicked(ClickedEventArgs e)
{
if (PadUnclicked != null)
PadUnclicked(this, e);
}
public virtual void OnPadTouched(ClickedEventArgs e)
{
if (PadTouched != null)
PadTouched(this, e);
}
public virtual void OnPadUntouched(ClickedEventArgs e)
{
if (PadUntouched != null)
PadUntouched(this, e);
}
public virtual void OnGripped(ClickedEventArgs e)
{
if (Gripped != null)
Gripped(this, e);
}
public virtual void OnUngripped(ClickedEventArgs e)
{
if (Ungripped != null)
Ungripped(this, e);
}
// Update is called once per frame
void Update()
{
var system = OpenVR.System;
if (system != null && system.GetControllerState(controllerIndex, ref controllerState, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t))))
{
ulong trigger = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Trigger));
if (trigger > 0L && !triggerPressed)
{
triggerPressed = true;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnTriggerClicked(e);
}
else if (trigger == 0L && triggerPressed)
{
triggerPressed = false;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnTriggerUnclicked(e);
}
ulong grip = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_Grip));
if (grip > 0L && !gripped)
{
gripped = true;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnGripped(e);
}
else if (grip == 0L && gripped)
{
gripped = false;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnUngripped(e);
}
ulong pad = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad));
if (pad > 0L && !padPressed)
{
padPressed = true;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnPadClicked(e);
}
else if (pad == 0L && padPressed)
{
padPressed = false;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnPadUnclicked(e);
}
ulong menu = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_ApplicationMenu));
if (menu > 0L && !menuPressed)
{
menuPressed = true;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnMenuClicked(e);
}
else if (menu == 0L && menuPressed)
{
menuPressed = false;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnMenuUnclicked(e);
}
pad = controllerState.ulButtonTouched & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad));
if (pad > 0L && !padTouched)
{
padTouched = true;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnPadTouched(e);
}
else if (pad == 0L && padTouched)
{
padTouched = false;
ClickedEventArgs e;
e.controllerIndex = controllerIndex;
e.flags = (uint)controllerState.ulButtonPressed;
e.padX = controllerState.rAxis0.x;
e.padY = controllerState.rAxis0.y;
OnPadUntouched(e);
}
}
}
}
二、实现发射子弹的功能##
public class Test_TrackedController :
SteamVR_TrackedController {
void Start () {
base.Start();
}
void Update () {
base.Update();
}
//事件的响应
public override void OnTriggerClicked(ClickedEventArgs e)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.position = this.gameObject.transform.position;
go.transform.localScale = new Vector3(0.1f,0.1f,0.1f);
go.AddComponent().AddForce(this.transform.forward * 100);
go.tag = "Player";
}
}