美文网首页
27VR开发——HTC Vive千里移动物体

27VR开发——HTC Vive千里移动物体

作者: _谭小坤 | 来源:发表于2017-03-09 09:56 被阅读95次

    实现的一个功能##

    大概实现的内容就是,扣动扳机的时候,如果指向一个在远处物体,那么可以吧远处的物体放到我们
    边上一个离我们很近的位置.这样就实现了从远处获取物体的功能.
    
    逻辑展示
    发射射线代码脚本展示:
    明确事件的发布,相应与调用:
    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<BoxCollider>();
            if (addRigidBody)
            {
                if (collider)
                {
                    collider.isTrigger = true;
                }
                Rigidbody rigidBody = pointer.AddComponent<Rigidbody>();
                rigidBody.isKinematic = true;
            }
            else
            {
                if(collider)
                {
                    Object.Destroy(collider);
                }
            }
            Material newMaterial = new Material(Shader.Find("Unlit/Color"));
            newMaterial.SetColor("_Color", color);
            pointer.GetComponent<MeshRenderer>().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<SteamVR_TrackedController>();
    
            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<SteamVR_LaserPointer>();//获取脚本
            
    
            pointer.PointerIn += Pointer_PointerIn;//PointerIn,是脚本里面的事件变量
            pointer.PointerOut += Pointer_PointerOut;//射线进入出去的两个方法
            
    
            obj = GetComponent<SteamVR_TrackedController>();//获取交互设备
            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<SteamVR_TrackedObject>().index);
            device.TriggerHapticPulse(2800);
            currentCatch.GetComponent<Rigidbody>().velocity = device.velocity * 5;
            currentCatch.GetComponent<Rigidbody>().angularVelocity = device.angularVelocity;
            Destroy(currentCatch.GetComponent<FixedJoint>());
            currentCatch = null;
        }
    
        private void Obj_TriggerClicked(object sender, ClickedEventArgs e)//扳机按下方法的执行
        {
            if (pointer==null)
            {
                return;
            }
            pointT.gameObject.AddComponent<FixedJoint>().connectedBody = this.GetComponent<Rigidbody>();
            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<SteamVR_TrackedObject>() == null)
            {
                gameObject.AddComponent<SteamVR_TrackedObject>();
            }
    
            if (controllerIndex != 0)
            {
                this.GetComponent<SteamVR_TrackedObject>().index = (SteamVR_TrackedObject.EIndex)controllerIndex;
                if (this.GetComponent<SteamVR_RenderModel>() != null)
                {
                    this.GetComponent<SteamVR_RenderModel>().index = (SteamVR_TrackedObject.EIndex)controllerIndex;
                }
            }
            else
            {
                controllerIndex = (uint) this.GetComponent<SteamVR_TrackedObject>().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<Rigidbody>().AddForce(this.transform.forward * 100);
            go.tag = "Player";
        }
    }
    

    相关文章

      网友评论

          本文标题:27VR开发——HTC Vive千里移动物体

          本文链接:https://www.haomeiwen.com/subject/hcjigttx.html