1
2
3
4
5
6
  • AR开发
7
8
  • 系统优化与发布

SteamVR

发布时间:2020-08-22 23:39   发布人:焦卫峰   浏览次数:497

1.SteamVR入门

1)已安装好Steam和SteamVR。

2)运行Unity,创建一个Project,在Asset Store中搜索Steam VR,安装好插件。

3)删除掉默认的Camera,在Project中选出Stream VR的CameraRig,拖入到场景中。

(拖入相关prefab 先删除所有默认GameObject ,然后将SteamVR/Prefabs中的所有prefab拖入Hierarchy窗口。)


[SteamVR]附加了一个Steam VR_Render组件,用于处理所有VR摄像机的渲染。

[CameraRig]控制着Vive的headset和控制器。 选择[CameraRig]并在Inspector中将其Position设置为(X:0,Y:0,Z:-1.1),以便在桌子后面滑动整个装备。

 

 

4)随便添加一些环境元素,然后运行。戴上你的Vive VR,就能看到刚刚设计的内容了。

 

大家可以参考SteamVR Plugin自带的示例场景,分别是:

 SteamVR/Scenes/example

 SteamVR/Extras/SteamVR_TestIK

 SteamVR/Extras/SteamVR_TestThrow

 

 

Unity开发小技巧:

请把 显示分辨率对话框属性设置为HiddenByDefault

在Unity 中Player Settings的选项里,https://docs.unity3d.com/Manual/class - PlayerSettingsStandalone.html

       

当用户带上HMD的时候我们没办法消除掉这个对话框,当启动游戏的时候,他们不得不摘下HMD手动消除这个对话框。但是这个对话框有时还是有用的,这就是为什么我推荐HiddenByDefault而不是Disable. Unity提供的方法是用命令行选项来控制当设置为HiddenByDefault(或者Ctrl),但是当设置为Enable的时候没有用。

 

https://www.bilibili.com/video/av59711404

 

2.steamVR 开发

本章节主要讲解使用SteamVR Plugins插件为基础,来介绍Vive开发的入门,重点讲解设备的激活和控制接口。SteamVR Plugins在unity官方资源商店可以免费下载,这里我就不给出链接了。

导入SteamVR Plugins后,不要在他的示例上去做开发,那样你会走弯路。因为这个插件的设备初始化代码很怪异,甚至可以说无法使用。因此我们需要自己写设备的初始化代码以及设备的操作接口。

我们对原插件进行封装后就可以愉快的使用了,之后怎么开发就和这个设备无关了,我们开发这类的应用无非是获取相关的接口操作。

新建场景,然后在Camera上添加组件SteamVR_Camera,然后点击 Expand 按钮,之后我们就得到了一个基本的VR相机。

然后我们在Camera的下面新建两个GameObject,并命名为LeftHand和RightHand。同时添加组件SteamVR_TrackedObject。然后在各自的下面添加一个对象名为Mode,并绑定组件SteamVR_RenderModel。

 

接下来就是开始写代码了,新建脚本SteamVR_InitManager.cs,来获取手柄的激活和相关的初始化代码

 

using UnityEngine;

using System.Collections;

using Valve.VR;

using System;

public class SteamVR_InitManager : MonoBehaviour

{

    public event Action<SteamVR_TrackedObject> OnLeftDeviceActive;//左手柄激活事件

    public event Action<SteamVR_TrackedObject> OnRightDeviceActive;//右手柄激活事件

 

    public SteamVR_TrackedObject LeftObject;

    public SteamVR_TrackedObject RightObject;

 

    private bool[] isAllConnect;//0代表右手状态,1代表左手状态

    private uint leftIndex = 100;//左手柄对应的设备ID

    private uint rightIndex = 100;//右手柄对应的设备ID

 

 

    private static SteamVR_InitManager instance;

 

    public DeviceInput LeftHandInput;

    public DeviceInput RightHandInput;

    public static SteamVR_InitManager Instance {

        get {

            if (instance == null) {

                instance = GameObject.FindObjectOfType<SteamVR_InitManager>();

            }

            return instance;

        }

    }

 

    // Use this for initialization

    void Awake()

    {

        LeftObject = transform.FindChild("LeftHand").GetComponent<SteamVR_TrackedObject>();

        RightObject = transform.FindChild("RightHand").GetComponent<SteamVR_TrackedObject>();

        LeftObject.gameObject.SetActive(false);

        RightObject.gameObject.SetActive(false);

    }

    void Start()

    {

        StartCoroutine(CheckDeviceActive());

    }

    void OnEnable()

    {

        OnLeftDeviceActive = LeftDeviceActive;

        OnRightDeviceActive = RightDeviceActive;

    }

    void OnDisable()

    {

        OnLeftDeviceActive -= LeftDeviceActive;

        OnRightDeviceActive -= RightDeviceActive;

    }

 

    /// <summary>

    /// 检测手柄设备是否激活

    /// </summary>

    /// <returns></returns>

    IEnumerator CheckDeviceActive()

    {

        yield return new WaitForSeconds(1);

        while (!isAllConnect[0] || !isAllConnect[1])

        {

            for (uint i = 1; i < OpenVR.k_unMaxTrackedDeviceCount; i )

            {

                if (i == leftIndex || i == rightIndex) continue;//已经初始化的不再进入判断

                if (OpenVR.System != null && OpenVR.System.IsTrackedDeviceConnected(i))

                {

                    OnDeviceConnected(new object[] { i, true });

                }

            }

 

            yield return new WaitForFixedUpdate();

        }

 

        yield return 0;

    }

 

    /// <summary>

    /// 检测激活的设备是否是手柄

    /// </summary>

    /// <param name="args"></param>

    private void OnDeviceConnected(object[] args)

    {

        if (args != null && args.Length > 1)

        {

            uint index = (uint)args[0];

            bool isConnect = (bool)args[1];

            var system = OpenVR.System;

            if (isConnect && system != null && system.GetTrackedDeviceClass(index) == ETrackedDeviceClass.Controller)

            {

                uint tmpleftIndex = (uint)system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);

                uint tmprightIndex = (uint)system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand);

                if (index == tmprightIndex)

                {

                    isAllConnect[0] = true;

                    rightIndex = index;

                    OnRightDeviceActive(RightObject);

                }

                else if (index == tmpleftIndex)

                {

                    isAllConnect[1] = true;

                    leftIndex = index;

                    OnLeftDeviceActive(LeftObject);

                }

            }

        }

    }

 

    private void RightDeviceActive(SteamVR_TrackedObject obj)

    {

        DeviceActive(obj, rightIndex);

        RightHandInput = obj.GetComponent<DeviceInput>();

    }

 

    private void LeftDeviceActive(SteamVR_TrackedObject obj)

    {

        DeviceActive(obj, leftIndex);

        LeftHandInput = obj.GetComponent<DeviceInput>();

    }

    /// <summary>

    /// 匹配对应的设备号,完成手柄模型的设置

    /// </summary>

    /// <param name="device"></param>

    /// <param name="index"></param>

    void DeviceActive(SteamVR_TrackedObject device, uint index)

    {

        SteamVR_TrackedObject.EIndex eIndex = (SteamVR_TrackedObject.EIndex)Enum.Parse(typeof(SteamVR_TrackedObject.EIndex), "Device" index);

        device.index = eIndex;

        device.GetComponentInChildren<SteamVR_RenderModel>().index = eIndex;

        device.gameObject.SetActive(true);

    }

 

}

 

3. 手柄控制接口代码

然后就是手柄控制接口代码DeviceInput.cs,基本上把所有的手柄控制事件都写完了.这个脚本添加到左右Hand对象上就行了。

 

using System;

using UnityEngine;

using Valve.VR;

/// <summary>

///

/// </summary>

 

public class DeviceInput : MonoBehaviour

{

    //Swipe directions

    public enum SwipeDirection

    {

        NONE,

        UP,

        DOWN,

        LEFT,

        RIGHT

    };

    public event Action OnPressTrigger;    //按住扳机键                          

    public event Action OnPressDownTrigger;  // 按下扳机键                            

    public event Action OnPressUpTrigger;    //抬起扳机键

    public event Action OnClickTrigger;  //单击扳机

 

    public event Action OnDoubleClickTrigger;  //双击扳机

    public event Action OnTouchPad;      //按住触摸板                       

 

    public event Action OnPressDownGripButton;   //按下侧键                          

    public event Action OnPressDownMenuButton;   //按下菜单键                         

    public event Action<Vector2> OnBeginTouch;  //触摸触摸板的位置                                

    public event Action<Vector2> OnEndTouch;//抬起触摸板的位置

 

    public event Action OnPressDownPad;  // 按下扳机键                            

    public event Action OnPressUpPad;    //抬起扳机键

    public event Action OnPressPad;    //抬起扳机键

    public event Action<Transform> OnPressDownPadV3;  // 按下扳机键                            

    public event Action<Transform> OnPressUpPadV3;    //抬起扳机键

    public event Action<Transform> OnPressPadV3;    //抬起扳机键

 

    public event Action OnTouchPadDown;  //按下触摸板                             

    public event Action OnTouchPadUp;//抬起触摸板

    public event Action<SwipeDirection> OnPadSwipe;

 

    [SerializeField]

    private float m_SwipeWidth = 0.6f;         //The width of a swipe

 

 

    private Vector2 m_PadDownPosition;                        // The screen position of the mouse when Fire1 is pressed.

    private float m_LastHorizontalValue;                        // The previous value of the horizontal axis used to detect keyboard swipes.

    private float m_LastVerticalValue;                          // The previous value of the vertical axis used to detect keyboard swipes.

 

    private SteamVR_TrackedObject Hand;

 

 

    private SteamVR_Controller.Device device;

    private Vector2 m_PadPosition;

    [SerializeField]

    private float m_DoubleClickTime = 0.3f;    //The max time allowed between double clicks

    private float m_LastMouseUpTime = 0;                            // The time when Fire1 was last released.

 

 

 

    public void Enable()

    {

        Hand = GetComponent<SteamVR_TrackedObject>();

 

    }

 

    public void Update()

    {

        CheckInput();

    }

 

    private void CheckInput()

    {

        // Set the default swipe to be none.

        SwipeDirection swipe = SwipeDirection.NONE;

        if (device == null)

        {

            device = SteamVR_Controller.Input((int)Hand.index);

            print("NUll Device");

            return;

        }

        if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Trigger))

        {

            if (OnPressTrigger != null) OnPressTrigger();

        }

        if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger))

        {

            if (OnPressDownTrigger != null) OnPressDownTrigger();

 

        }

        if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger))

        {

            if (OnPressUpTrigger != null) OnPressUpTrigger();

            if (Time.time - m_LastMouseUpTime < m_DoubleClickTime)

            {

                if (OnDoubleClickTrigger != null)

                    OnDoubleClickTrigger();

            }

            else

            {

                if (OnClickTrigger != null)

                    OnClickTrigger();

            }

            m_LastMouseUpTime = Time.time;

        }

        if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnPressDownPad != null) OnPressDownPad();

            if (OnPressDownPadV3 != null) OnPressDownPadV3(transform);

        }

        if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnPressUpPad != null) OnPressUpPad();

            if (OnPressUpPadV3 != null) OnPressUpPadV3(transform);

        }

        if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnPressPad != null) OnPressPad();

            if (OnPressPadV3 != null) OnPressPadV3(transform);

        }

        if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnTouchPad != null) OnTouchPad();

            m_PadPosition = device.GetAxis();

        }

        if (device.GetTouchUp(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnTouchPadUp != null) OnTouchPadUp();

            if (OnEndTouch != null) OnEndTouch(m_PadPosition);

            swipe = DetectSwipe();

            m_PadDownPosition = Vector2.zero;

        }

        if (device.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad))

        {

            if (OnTouchPadDown != null) OnTouchPadDown();

            if (OnBeginTouch != null) OnBeginTouch(m_PadDownPosition = device.GetAxis());

        }

        if (device.GetPressDown(EVRButtonId.k_EButton_Grip))

        {

            if (OnPressDownGripButton != null) { OnPressDownGripButton(); }

        }

        if (device.GetPressDown(EVRButtonId.k_EButton_ApplicationMenu))

        {

            if (OnPressDownMenuButton != null) OnPressDownMenuButton();

        }

 

        if (swipe != SwipeDirection.NONE)

        {

            if (OnPadSwipe != null) OnPadSwipe(swipe);

            if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad))

            {

                m_PadPosition = device.GetAxis();

            }

            else {

                m_PadDownPosition = Vector2.zero;

            }

        }

    }

 

    private SwipeDirection DetectSwipe()

    {

        // Get the direction from the mouse position when Fire1 is pressed to when it is released.

        Vector2 swipeData = (m_PadPosition - m_PadDownPosition).normalized;

        //print(m_PadPosition "   " m_PadDownPosition "  " swipeData);

 

        // If the direction of the swipe has a small width it is vertical.

        bool swipeIsVertical = Mathf.Abs(swipeData.y) > m_SwipeWidth;

 

        // If the direction of the swipe has a small height it is horizontal.

        bool swipeIsHorizontal = Mathf.Abs(swipeData.x) > m_SwipeWidth;

        // If the swipe has a positive y component and is vertical the swipe is up.

        if (swipeData.y > 0f && swipeIsVertical)

            return SwipeDirection.UP;

 

        // If the swipe has a negative y component and is vertical the swipe is down.

        if (swipeData.y < 0f && swipeIsVertical)

            return SwipeDirection.DOWN;

 

        // If the swipe has a positive x component and is horizontal the swipe is right.

        if (swipeData.x > 0f && swipeIsHorizontal)

            return SwipeDirection.RIGHT;

 

        // If the swipe has a negative x component and is vertical the swipe is left.

        if (swipeData.x < 0f && swipeIsHorizontal)

            return SwipeDirection.LEFT;

 

        // If the swipe meets none of these requirements there is no swipe.

        return SwipeDirection.NONE;

    }

 

    public void Disable()

    {

        OnPressTrigger = null;    //按住扳机键                          

        OnPressDownTrigger = null;  // 按下扳机键                            

        OnPressUpTrigger = null;    //抬起扳机键                             

        OnTouchPad = null;      //按住触摸板                       

        OnPressDownGripButton = null;   //按下侧键                          

        OnPressDownMenuButton = null;   //按下菜单键                         

        OnBeginTouch = null;  //触摸触摸板的位置                                 

        OnEndTouch = null;//抬起触摸板的位置

        OnTouchPadDown = null;  //按下触摸板                             

        OnTouchPadUp = null;//抬起触摸板

        OnPadSwipe = null;

    }

}

4.测试

接下来写一个简单的测试类来测试相关的代码:TestEvent.cs

using UnityEngine;

using System.Collections;

using System;

/// <summary>

/// 这是一个测试类,简单的测试了手柄的激活以及部分手柄的操作事件

/// 两个手柄分开注册,这样扩展性非常好,相同的按键可以做不同的处理

/// 大家可以补充测试

/// </summary>

public class TestEvent : MonoBehaviour {

 

    void OnEnable() {

        SteamVR_InitManager.Instance.OnLeftDeviceActive = OnLeftDeviceActive;//左手柄激活

        SteamVR_InitManager.Instance.OnRightDeviceActive = OnRightDeviceActive;//右手柄激活

    }

 

    private void OnRightDeviceActive(SteamVR_TrackedObject obj)

    {

        print("OnRightDeviceActive" obj);

        SteamVR_InitManager.Instance.RightHandInput.OnPressDownTrigger = OnPressDownTrigger;

        SteamVR_InitManager.Instance.RightHandInput.OnTouchPadDown = OnTouchPadDown;

    }

 

    private void OnPressDownTrigger()

    {

        print("OnPressDownTrigger");

    }

 

    private void OnTouchPadDown()

    {

        print("OnTouchPadDown");

    }

 

    private void OnLeftDeviceActive(SteamVR_TrackedObject obj)

    {

        print("OnLeftDeviceActive" obj);

        SteamVR_InitManager.Instance.LeftHandInput.OnPressDownTrigger = OnPressDownTrigger;

        SteamVR_InitManager.Instance.LeftHandInput.OnTouchPadDown = OnTouchPadDown;

 

    }

 

    void OnDisable() {

        SteamVR_InitManager.Instance.OnLeftDeviceActive -= OnLeftDeviceActive;//左手柄激活

        SteamVR_InitManager.Instance.OnRightDeviceActive -= OnRightDeviceActive;//右手柄激活

    }

}

5. SteamVR 抛物线移动

其实实现抛物线很简单,生成一组抛物点,然后将点渲染成线就好。渲染成线有很多方式,你可以用模型,也可以用GL的绘制线段,也可以用LineRender。重点是优化点的生成计算。

如何生成抛物点,一个很简单的公式:

nextPos = lastPos 水平位移 垂直位移。

 

稍后的代码有详尽的注释我就不多赘述了。

重点是对点集的优化,优化抛物点分两个部分,一是如何计算碰撞点,二是内存开销的优化。考虑到一般的VR项目只在水平面上进行移动,所以通过判断抛物点的y轴来判定碰撞。关于内存开销,我们可以限定生成的抛物点个数,同时优化计算。我们使用一个List来保存点集,动态的根据点的情况来生成点,或者改变点的位置。例如当手柄角度不变时,只需要将List集合中的点改变Y轴就行了。

 

现在思路已经明了了。以下是伪代码:

int i = 0;

while( nextPos.y>0 && maxPoint>0 ){

if(list.count<=i){

list.add(nextPos);

}

else{

list = nextPos;

}

///生成,优化,计算下一个抛物点

i ;

}

list.remove(i,list.count-i);//移除上一个点集的多余数据

生成抛物线点集后,接下来就是绘制曲线,LineRender,GL都可以很方便的绘制。但是就性能来说,GL更加快一点。建议大家用GL。当然大家也可以使用自己的模型绘制,原理就是,在对应的点生成你的模型,然后计算对应的角度即可。

最后就是生成抛物线的终点,是按照y轴来判断抛物线的落点,但是落点可能有障碍物等等,或者落点在墙角,这些位置显然是不能跳跃的,所以需要对落点进行判断。在Physics中有一个方法可以检测一个球形范围是否会碰撞,可以给地面添加一个层,以便忽略地面的检测,这样就可以安全的着陆了。

 

using UnityEngine;

using System.Collections.Generic;

using System;

 

/// <summary>

/// 抛物线脚本

/// </summary>

public class HandRay : MonoBehaviour

{

 

    private Transform CurrentHand; //当前触发的手

    private List<Vector3> pointList; //曲线点集合

    private Quaternion lastRotation; //上一个移动的角度

    private Vector3 lastPostion; //上一个位置

    private Vector3 lastPos; //上一个点,为了优化将一个临时变量做成全局的,节省内存开销

    private Vector3 nextPos;//下一个点,理由同上

    private event Action OnChangeTransform;//一个事件,用来检测手柄位置和角度变化的

    private Material material;//渲染射线的材质球

    private Vector3 HitPoint;//抛物线的碰撞点

    private Ray ray;

    private bool canJump = false;//

 

    public GameObject PointEffect;//一个特效,就是在射线的终点放置一个光柱什么的,大家可以自己做这个特效

 

    public int MaxPoint;  //生成曲线的点最大数量

    public float Distence;//水平位移

    public float Grity;//垂直位移

    public float CheckRange;//检测位置是否存在障碍物

 

    public void Awake()

    {

        SetData();

    }

 

    public void Start()

    {

        pointList = new List<Vector3>();

        OnChangeTransform = OnChangeTransformCallBack;

        HitPoint = -Vector3.one;

        ray = new Ray();

 

 

    }

    public void Update()

    {

        //当手柄按下触摸键同时角度合适时触发事件开始计算点

        if (CurrentHand != null && ((CurrentHand.eulerAngles.x > 275 && CurrentHand.eulerAngles.x <= 360) || (CurrentHand.eulerAngles.x >= -0.01f && CurrentHand.eulerAngles.x < 85)))

        {

            if (OnChangeTransform != null) OnChangeTransform();

        }

        else

        {

            pointList.Clear();

            PointEffect.SetActive(false);

        }

    }

    /// <summary>

    /// 计算抛物线的点

    /// 此方法已经优化过性能

    ///

    /// </summary>

    private void OnChangeTransformCallBack()

    {

        if (lastRotation != CurrentHand.rotation || lastPostion != CurrentHand.position)

        {

            lastPos = nextPos = CurrentHand.position;

            int i = 0;

            while (nextPos.y > 0 && (i < MaxPoint))

            {

                if (pointList.Count <= i)

                {

                    pointList.Add(nextPos);

                }

                else

                {

                    pointList[i] = nextPos;

                }

                if (lastRotation == CurrentHand.rotation && lastPostion != CurrentHand.position && i < pointList.Count - 1)

                {

                    nextPos = pointList[i 1] CurrentHand.position - lastPostion;

                }

                else

                {

                    nextPos = lastPos CurrentHand.rotation * Vector3.forward * Distence Vector3.up * Grity * 0.1f * i * Time.fixedDeltaTime;

                }

                lastPos = nextPos;

                i ;

            }

            if (pointList.Count > i)

            {

                pointList.RemoveRange(i, pointList.Count - i);

            }

            lastRotation = CurrentHand.rotation;

            lastPostion = CurrentHand.position;

            if (pointList.Count > 1)

            {

                HitPoint = pointList[pointList.Count - 1];

                PointEffect.SetActive(true);

                PointEffect.transform.position = HitPoint;

            }

            else

            {

                HitPoint = -Vector3.one;

                PointEffect.SetActive(false);

            }

        }

    }

 

    public void Enable()

    {

        SteamVR_InitManager.Instance.OnLeftDeviceActive = OnHandActive;

        SteamVR_InitManager.Instance.OnRightDeviceActive = OnHandActive;

        OnChangeTransform = OnChangeTransformCallBack;

    }

    public void OnHandActive(SteamVR_TrackedObject obj)

    {

        DeviceInput device = obj.GetComponent<DeviceInput>();

        device.OnPressDownPadV3 = OnPressDownPad;

        device.OnPressUpPad = OnPressUpPadAction;

    }

 

    public void OnHandDis(SteamVR_TrackedObject obj)

    {

        if (obj && obj.gameObject.activeSelf)

        {

            DeviceInput device = obj.GetComponent<DeviceInput>();

            device.OnPressDownPadV3 -= OnPressDownPad;

            device.OnPressUpPad -= OnPressUpPadAction;

        }

    }

 

    public void Disable()

    {

        SteamVR_InitManager.Instance.OnLeftDeviceActive -= OnHandActive;

        SteamVR_InitManager.Instance.OnRightDeviceActive -= OnHandActive;

        OnHandDis(SteamVR_InitManager.Instance.LeftObject);

        OnHandDis(SteamVR_InitManager.Instance.LeftObject);

        OnChangeTransform -= OnChangeTransformCallBack;

    }

 

    public void SetData()

    {

        if (PointEffect)

            PointEffect.SetActive(false);

    }

 

    /// <summary>

    /// 抬起触摸板时,计算落脚点

    /// </summary>

    private void OnPressUpPadAction()

    {

        if (CurrentHand == null) return;

        canJump = true;

        ray.origin = CurrentHand.position;

        Vector3 dir = HitPoint - CurrentHand.position;

        ray.direction = dir;

        if (Physics.CheckSphere(HitPoint, CheckRange, ~(1 << 8)))

        {

            canJump = false;

        }

        if (canJump)

        {

            JumpPoint(HitPoint);

        }

        CurrentHand = null;

    }

    /// <summary>

    /// 跳到指定的点

    /// </summary>

    /// <param name="point"></param>

    public void JumpPoint(Vector3 point)

    {

        point.y = transform.position.y;

        transform.position = point;

    }

 

    private void OnPressDownPad(Transform parent)

    {

 

        CurrentHand = parent;

 

    }

 

    /// <summary>

    /// 使用GL来绘制曲线

    /// 将点绘制出来

    /// </summary>

    void OnRenderObject()

    {

        material.SetPass(0);

        if (pointList == null) return;

        GL.Begin(GL.LINES);

        for (int i = 0; i < pointList.Count; i )

        {

            GL.Vertex(pointList[i]);

        }

        GL.End();

    }

 

    /// <summary>

    /// 一个额外的附加方法,即用一个曲线来绘制抛物线,性能较低,因为点数比较多

    /// 感兴趣的可以把此方法添加到Update中更新

    /// </summary>

 

    public void ShowLineByRender()

    {

 

        LineRenderer line = GetComponent<LineRenderer>();

        if (line)

        {

            line.SetVertexCount(pointList.Count);

            for (int i = 0; i < pointList.Count; i )

            {

                line.SetPosition(i, pointList[i]);

            }

        }

    }

}

 

6. 手柄和物体的交互事件