快速開發實用工具VRTK-001:005

DEMO 1 場景切換、簡單獲取手柄並監控按鈕

第一個場景001_CameraRig_VRPlayArea,它的功能是按下手柄任意鍵切換到下一個場景。你需要做的準備工作是準備好切換的下一個場景,也就是要先創景一個場景,然後在場景中添加VRTK的VR攝像機和SceneChanger腳本。這裏說一點,當前版本的VRTK的prefabs包裏沒有拉出來就可以用的VR攝像頭,要自己做,先創建一個gameObject,改名爲VRTK_SDKManager,然後添加VRTK_SDKManager腳本,然後添加預置物SDKSetups然後VRTK_SDKManager下面有個AutoPopulate按鈕,按下後就會自動組合成一個VR攝像機了。

圖片01.png

圖片02.png

圖片03.png

添加SceneChanger場景切換腳本。

圖片04.png

最後一步就是到Build Settings哪裏把場景添加上去。

圖片05.png

然後來講一下場景切換是怎麼運作的,SceneChanger腳本里有兩個個核心類:
VRTK_DeviceFinder類:用於在場景中尋找左右手柄、頭顯、返回硬件編號或手柄,頭顯的gameobject。

 

GameObject rightHand = VRTK_DeviceFinder.GetControllerRightHand(true);

VRTK_SDK_Bridge類:這是插件封裝了 SteamVR 的比較底層的;APIVRTK_SDK_Bridge.IsTriggerPressedOnIndex(controllerIndex) 。輸入硬件的編號,返回是否按下的布爾值。

 

VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.Trigger, SDK_BaseController.ButtonPressTypes.Press, controllerReference);

重要的API:
獲得左右手柄的遊戲物體
VRTK_DeviceFinder.GetControllerRightHand();
VRTK_DeviceFinder.GetControllerLiftHand();
獲得左右手柄對應的硬件編號
VRTK_DeviceFinder.GetControllerIndex(rightHand)

圖片6.png

圖片07.png

DEMO 2 發射激光與手柄的事件輸入

Toolkit把所有手柄事件都封裝到VRTK_ControllerEvents裏,針對VR中常見的交互動作: UI點擊,抓住物體,觸發物體功能等,自定義手柄按鍵,綁定這些動作,下面對腳本逐塊代碼塊進行講解。

Inspector面板上的可見參數:

· Pointer Toggle Button:用於控制一束激光指示線開/關,相當於鼠標的指向功能。
· Pointer Set Button:用於設置激光指向的目標標記,觸發目標的功能,相當於鼠標點擊。
· Grab Toggle Button:用於控制抓取遊戲中的物體,配合使用VRTK插件集成的抓取,投擲功能.
· Use Toggle Button:用於觸發目標事件,比如把手柄放在門把手上,按下這個按鍵,觸發門打開的功能,手柄放在電燈開關上,按下按鍵,觸發電燈開發的功能(這個和pointerSetButton區別在於後者需要激光落在目標上,才能觸發目標上的功能)。
· UI Click Button::用於觸發UI Canvas 目標的事件。
· Menu Toggle Button:用於點擊彈出遊戲內置按鈕,遊戲目錄顯示開關。
· Axis Fidelity:按鍵按下的強度,完全按下是1,鬆開時是0, 現在只有Trigger按鍵(手部後面扳機)有此屬性
· triggerClickThreShold: 扳機要到多大程度,才能使用扳機的觸發功能. 如果是0.5 ,則表示只要按下一半的程度就可以觸發,如果是1,則必須完全按下才能觸發.

圖片08.png

VRTK_ControllerEvents裏一些重要變量的解釋:

· public bool triggerPressed - 當trigger被扣下一半左右時爲真.
· public bool triggerTouched - 當trigger被扣下一點點時爲真.
· public bool triggerHairlinePressed - 當trigger比任何之前扣下的程度多時爲真.
· public bool triggerClicked - 當trigger完全扣下時爲真.
· public bool triggerAxisChanged - 當trigger位置改變時爲真.
· public bool applicationMenuPressed - 當application menu被按下時爲真.
· public bool touchpadPressed - 當touchpad被按下時爲真.
· public bool touchpadTouched - 當touchpad被觸碰時爲真.
· public bool touchpadAxisChanged - 當touchpad觸碰位置改變時爲真.
· public bool gripPressed - 當grip被按下時爲真.
· public bool pointerPressed - 當別名爲pointer的按鈕被按下時爲真.
· public bool grabPressed - 當別名爲grab的按鈕被按下時爲真.
· public bool usePressed - 當別名爲use的按鈕被按下時爲真.
· public bool uiClickPressed - 當別名爲UI click的按鈕被按下時爲真.
· public bool menuPressed - 當別名爲menu的按鈕被按下時爲真.

圖片09.png

聲明事件裝載參數ControllerInteractionEventArgs :

圖片10.png

腳本里包含的事件:

· TriggerPressed - 當trigger被扣下一半左右時發送事件.
· TriggerReleased - 當Trigger從扣下一半的狀態釋放後發送事件.
· TriggerTouchStart - 當trigger被扣下一點點時發送事件.
· TriggerTouchEnd - 當trigger完全沒有被扣下時發送事件.
· TriggerHairlineStart - 當trigger扣下的程度超過了當前的hairline閾值時發送事件.
· TriggerHairlineEnd - 當tringger釋放程度超過了當前的hairline閾值時發送事件.
· TriggerClicked - 當trigger在clicked之前扣下的過程中發送事件.
· TriggerUnclicked - 當trigger不再一直處於clicked狀態時發送事件.
· TriggerAxisChanged - 當trigger扣下的量發生變化時發送事件.
· ApplicationMenuPressed - 當application menu被按下時發送事件.
· ApplicationMenuReleased - 當application menu被釋放時發送事件.
· GripPressed - 當grip被按下時發送事件.
· GripReleased - 當grip被釋放時發送事件.
· TouchpadPressed - 當touchpad被按下的時候發送事件(比觸摸的按壓程度大).
· TouchpadReleased - 當touchpad從被按下(非觸碰)的狀態下釋放時發送事件.
· TouchpadTouchStart - 當touchpad被觸摸時發送事件 (不是點擊或者摁下).
· TouchpadTouchEnd - 當touchpad不再被觸摸時發送事件.
· TouchpadAxisChanged - 當touchpad被觸摸的點改變時發送事件.
· AliasPointerOn - 當pointer toggle(別名)被按下的時候發送事件.
· AliasPointerOff - 當pointer toggle(別名)被釋放的時候發送事件.
· AliasPointerSet - 當pointer set(別名)被釋放時發送事件.
· AliasGrabOn - 當grab toggle(別名)被按下的時候發送事件.
· AliasGrabOff - 當grab toggle(別名)被釋放的時候發送事件.
· AliasUseOn - 當use toggle(別名)被按下的時候發送事件.
· AliasUseOff - 當use toggle(別名)被釋放時發送事件.
· AliasMenuOn - 當menu toggle(別名)被按下時發送事件.
· AliasMenuOff - 當menu toggle(別名)被釋放時發送事件.
· AliasUIClickOn - 當UI click(別名)被按下時發送事件.
· AliasUIClickOff - 當UI click(別名)被釋放時發送事件.

事件和bool狀態變量有着對應的關係,通常一個bool狀態變量會對應至少兩個按鈕事件

按鈕的別名:

圖片11.png

這個工具類給Vive手柄一些常用的操作取一些別名,和實際的按鈕建立映射,例如:
public ButtonAlias menuToggleButton = ButtonAlias.Application_Menu;
這個menuToggleButton與SteamVR中的SteamVR_Controller.ButtonMask.ApplicationMenu
對應,當這個按鈕被按下時,別名按鈕對應的事件(如果有綁定)也會發送。

和SteamVR相關的全局變量

1、private uint controllerIndex; —— controllerIndex - 手柄的索引值,通過trackedController.index獲取
2、private SteamVR_TrackedObject trackedController;—— controllerIndex - 手柄的索引值,通過trackedController.index獲取
3、private SteamVR_Controller.Device device;—— device - 設備類,通過此類獲取實際中手柄的各種數據
4、private Vector2 touchpadAxis = Vector2.zero;—— touchpadAxis - 全局變量,touchpad的座標
5、private Vector2 triggerAxis = Vector2.zero;—— triggerAxis - 全局變量,trigger的座標
6、private float hairTriggerDelta;——
7、private Vector3 controllerVelocity = Vector3.zero;—— controllerVelocity - 手柄運動的速度
8、private Vector3 controllerAngularVelocity = Vector3.zero;—— controllerAngularVelocity - 手柄旋轉的角速度

事件發送方法:

以OnTriggerPressed方法爲例,其他都和這個差不多

 

public virtual void OnTriggerPressed(ControllerInteractionEventArgs e)
{
    if (TriggerPressed != null)
    {
        TriggerPressed(this, e);//發送事件,通知綁定此事件的腳本,執行具體的邏輯,但是此處是真正最後調用的地方
    }
}

事件的參數裝載方法SetButtonEvent

該方法返回一個ControllerInteractionEventArgs參數;

 

private ControllerInteractionEventArgs SetButtonEvent(ref bool buttonBool, bool value, float buttonPressure)
{
    buttonBool = value;
    ControllerInteractionEventArgs e;
    e.controllerIndex = controllerIndex;
    e.buttonPressure = buttonPressure;
    e.touchpadAxis = device.GetAxis();//調用SteamVR API獲取當前的touchpad二維座標
    e.touchpadAngle = CalculateTouchpadAxisAngle(e.touchpadAxis);//計算二維座標在圓形錶盤上對應的角度
    return e;
}

通過傳入ref bool buttonBool,可以在對ControllerInteractionEventArgs進行裝填的同時,把事件對應的按鈕bool狀態進行更新,例如TriggerPressed和TriggerReleased事件對應的按鈕bool狀態是triggerPressed,當發送TriggerPressed事件時要同時更新triggerPressed爲true;發送TriggerReleased事件時要同時更新triggerPressed爲false

初始化代碼

 

private void Awake()
{
    trackedController = GetComponent();
    gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");
}
private void Start()
{
    //獲取當前腳本attach的Controller的index
    controllerIndex = (uint)trackedController.index;
    if (controllerIndex < uint.MaxValue)
    {
        //獲取設備
        device = SteamVR_Controller.Input((int)controllerIndex);
    }
}

一般頭顯對應的index爲0,兩個手柄分別爲0和1

別名按鈕事件發送

 

private void EmitAlias(ButtonAlias type, bool touchDown, float buttonPressure, ref bool buttonBool)
…
        if (pointerToggleButton == type)
        {
            if (touchDown)
            {
                pointerPressed = true;
                OnAliasPointerOn(SetButtonEvent(ref buttonBool, true, buttonPressure));
            }
            else
            {
                pointerPressed = false;
                OnAliasPointerOff(SetButtonEvent(ref buttonBool, false, buttonPressure));
            }
        }
…

根據type判斷是哪個別名按鈕,最後一個參數buttonBool對應的是非別名的按鈕bool狀態,例如這個pointerToggleButton,發送事件時要把touchpadPressed狀態更新,而更新爲true還是false要根據touchDown的值來判斷,上面的OnAliasPointerOn等方法和OnTriggerPressed
  值得注意的是,不同的別名對應的可能是相同的按鈕,例如pointerToggleButton和pointerSetButton都是ButtonAlias.Touchpad_Press。

禁用事件

 

private void OnDisable()
{
    //在0.1s內調用DisableEvents(),禁用所有事件發送
    Invoke("DisableEvents", 0.1f);
}
///
/// 禁用,還原,但是保存touchpad和trigger的座標等
///
private void DisableEvents()
{
    if (triggerPressed)
    {
        OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));
        EmitAlias(ButtonAlias.Trigger_Press, false, 0f, ref triggerPressed);
    }
    ...
    triggerAxisChanged = false;
    touchpadAxisChanged = false;
    controllerIndex = (uint)trackedController.index;
    if (controllerIndex < uint.MaxValue)
    {
        device = SteamVR_Controller.Input((int)controllerIndex);
        Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
        Vector2 currentTouchpadAxis = device.GetAxis();
        // 保存當前的touchpad和trigger的設置.
        touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
        triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
        hairTriggerDelta = device.hairTriggerDelta;
    }
}

這個方法應該就是將所有事件對應的按鈕bool狀態置爲false,同時保存touchpad和trigger上的座標信息,但是爲什麼要重新獲取一次device呢?

Update()方法

 

private void Update()
{
    controllerIndex = (uint)trackedController.index;
    //Only continue if the controller index has been set to a sensible number
    //SteamVR 在未找到Controller時會把index置爲uint最大的值
    if (controllerIndex >= uint.MaxValue)
    {
        return;
    }
    device = SteamVR_Controller.Input((int)controllerIndex);
    Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
    Vector2 currentTouchpadAxis = device.GetAxis();
    //Trigger Pressed
    if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
    {
        //發送事件,設triggerPressed爲true,同時發送Trigger_Press對應的別名按鈕事件
        OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));
        EmitAlias(ButtonAlias.Trigger_Press, true, currentTriggerAxis.x, ref triggerPressed);
    }
    else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger))
    {
        OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));
        EmitAlias(ButtonAlias.Trigger_Press, false, 0f, ref triggerPressed);
    }
    ...
    // 保存當前trigger和touchpad狀態.
    touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
    triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
    hairTriggerDelta = device.hairTriggerDelta;
}

這裏要說一下,這腳本每幀監聽一次SteamVR中的控制柄狀態,而當監聽到狀態後,執行一次自己的委託事件(ControllerInteractionEventHandler),並且執行一次EmitAlias也就是別名按鈕事件(ButtonAlias type, bool touchDown, float buttonPressure, ref bool buttonBool)。EmitAlias方法是用來判斷並分發事件給AliasXX(oN/oFF)的,AliasXX(oN/oFF)這些委託方法就是上面提過的Inspector面板中的

圖片12.png

· Pointer Toggle Button: 這個按鈕用於控制一束激光指示線開/關.
· Pointer Set Button: 這個按鈕用於設置指示線的目標標記.
· Grab Toggle Button: 這個按鈕用於控制抓取遊戲中的物體.
· Use Toggle Button: 這個按鈕用於使用遊戲中的物體.
· UI Click Button: 這個按鈕用於點擊UI元素.
· Menu Toggle Button:這個按鈕用於點擊彈出遊戲內置按鈕.

使用實例

例如在VRTK_ControllerEvents_ListenerExample中

 

GetComponent().TriggerPressed += new ControllerInteractionEventHandler(DoTriggerPressed);
private void DoTriggerPressed(object sender, ControllerInteractionEventArgs e)
{
    DebugLogger(e.controllerIndex, "TRIGGER", "pressed", e);
}

獲取到當前Controller綁定的VRTK_ControllerEvents腳本,爲它的TriggerPressed綁定DoTriggerPressed方法,在VRTK_ControllerEvents腳本中,每一幀會檢測trigger是否被按下,如果按下,則發送事件

 

OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));

然後在OnTriggerPressed方法裏執行TriggerPressed(this, e);
  此時Example中的DoTriggerPressed(this,e)被真正調用,而VRTK_ControllerEvents_ListenerExample腳本中無需在update中寫代碼,只需要在初始化的時候綁定事件就可以了。

DEMO 3 手柄的激光指針

第三個場景主要添加的腳本是VRTK_Pointer和VRTK_StraightPointerRenderer,它們都在Pointer文件夾裏。

圖片13.png

這裏有一點要說到,在第二個demo中其實也有用到的,就是另外創建一個空物體,並在空物體下面添加兩個空物體以代替兩個手柄的事件引用操作,分別添加VRTK_ControllerEvents腳本,然後在VR攝像機[VRTK_SDKManager]下Script Aliases欄下分別綁定新創建的兩個手柄引用,這樣的好處就是能更簡潔地管理手柄的觸發事件,添加功能,這樣更便於管理並且不會破壞[CameraTig]物體的Prefab。

圖片14.png

圖片15.png

回過頭來我們來了解一下VRTK_Pointer和VRTK_StraightPointerRenderer這兩個腳本。
VRTK_Pointer繼承於VRTK_DestinationMaker,VRTK_StraightPointerRenderer繼承於VRTK_BasePointerRenderer;這是新版本的激光指針腳本,以前是隻有一個腳本而已,新版本分成了兩個,據我的瞭解,VRTK_StraightPointerRenderer是負責創建和激光屬性的調節,VRTK_Pointer是負責對激光觸發的功能進行管理。

圖片16.png

VRTK_Pointer

Destination Marker Settings 目的地標記設定
Enable Teleport(啓動傳送):如果勾選了,在目標設置事件中的teleport標誌位就設爲true,所以傳送腳本就知道是否要行動到新的目標。如果這個選項沒有勾選的話,控制器光束啓動但是不會觸發位移。
Target List Policy:設置限制位移的物體,如果有物體的Tag被設置爲在VRTK_Policy List中設置的Tag之一的話,那麼將無法傳送到該物體上。
Pointer Activation Settings 指針激活設定
Pointer Renderer:獲取要控制的VRTK_Straight Pointer Renderer渲染器。
Activation Button:激活或禁用指針按鈕。
Hold Button To Activate:勾上時需要一直按按鈕才能激活射線,否則按一下按鈕激活按一下按鈕就不激活。??
Activation On Enable:??
Activation Delay:激活延遲??
Pointer Selection Settings 指針選擇設定??
媽蛋查來查去都不知道這些屬性什麼意思,還是先了解各個Demo的功能和使用方法,細節以後再補上了!!

VRTK_Straight Pointer Renderer

Playarea Cursor :遊玩區光標和碰撞的尺寸,舊版中只是設置它的X和Y,現在新版中有個專門用來控制遊玩區域的腳本VRTK_PlayAreaCursor,這裏選的就是它。
Direction Indicator:方向指示器,有個VRTK_Pointer Direction Indicator腳本,跟上面一樣要加到手柄上然後選擇它。
Custom Raycast:有個VRTK_Custom Raycast腳本,要添加這個腳本

反正這個腳本就是實現從手柄發出激光射線,並且可以拓展出各種功能。

DEMO 4 傳送

主角是VRTK_BasicTeleport腳本,和上面VRTK_Pointer和VRTK_Straight Pointer Renderer腳本聯用,要有VRTK_BasicTeleport才能實現瞬移功能,具體操作很簡單,在手柄上添加了VRTK_Pointer和VRTK_Straight Pointer Renderer腳本後,在手柄的同一父物體下創建一個空物體命名爲PlayArea,然後添加VRTK_BasicTeleport腳本就行了,還有就是如果想用曲線做瞬移,只要把VRTK_Straight Pointer Renderer腳本換成VRTK_Bezier Pointer Renderer。

圖片17.png

VRTK_BasicTeleport

Blink To Color:傳送時的黑屏顏色,模擬眨眼,過渡更自然。
Blink Transition Speed:黑屏的褪色速度,根據你的需要設置,爲0的話就不會有褪色閃爍效果。
Distance Blink Delay:黑屏時間延遲,隨傳送距離遠近成正比的黑屏時間。假如傳送的位置比較遠,則黑屏時間更久。數值越大,黑屏時間越長,數值爲0時,不受距離遠近影響。
Headset Position Compensation:以頭部爲基準,作爲傳送的位置。未打鉤,則是玩家可玩區域的中心位置作爲傳送的目標點。可玩區域不能和遊戲環境交叉,最大化玩家活動空間。
Target List Policy:可以添加 VRTK_TagOrScriptPolicyList 腳本,其中添加多個禁止傳送的物體標籤。
Nav Mesh Limit Distance:navemesh 邊緣限制,在 navemesh 上傳送,如果在 navemesh 的邊界,則禁止傳送,數值是離邊界的距離範圍。

DEMO 5 抓取物體

主要用到的腳本是VRTK_Interact Touch、VRTK_Interact Grab和VRTK_Interactable Object。前面兩個是放到手柄上,後面那個是放到可抓取物體上的。

VRTK_Interact Touch

圖片18.png

Custom Collider Container:一個可選的GameObject,它包含複合碰撞器來表示觸碰對象。 如果這是空的,那麼在運行時會自動生成碰撞器,以配合SDK默認控制器。

VRTK_Interact Grab

Grab Settings 抓取設定
Grab Button:設置抓取觸發按鈕。
Grab Precognition:提前預判抓取物體。如果物體以快速的速度移動,那麼由於人的反應時間,很難及時按下抓取按鈕來捕捉物體。 這裏的較高的數字意味着在控制器觸摸對象之前可以按下抓取按鈕,值越大,可提前的抓取時間越長,並且當碰撞發生時,如果抓住按鈕仍然被按下,則抓取動作將成功。
Throw Multiplier:用來乘以對象被扔出時速度的量。在放大 CameraRig 來模擬能夠把物體扔的更遠時是很有用的。
Create Rigid Body When Not Touching:在碰到物體時才創建 RigidBody。當抓取按鈕按下時,如果控制器沒有碰到一個可交互的對象,那麼添加到控制器上的剛體就允許控制器去推動周圍其他的剛體對象。
Controller Attach Point:設置控制器上的一個將抓住的物體固定住剛體點。 如果爲空,它將被設置爲SDK默認值。
Controller EventsInteract Touch就是當前控制器上的VRTK_Controller Events和VRTK_Interact Grab腳本,這裏會自動獲取,不需要設置。

VRTK_Interactable Object

圖片19.png

Disable When Idle:如果這被監控到對象沒有被交互時,可以禁用交互對象腳本。 這將消除可交互對象對每個幀的潛在呼叫數量。
Touch Options 觸摸設置
Touch Highlight Color:觸摸到時的高亮顏色。顏色可以被任何全局的設置顏色來覆寫(例如InteractTouch 腳本)。
Allowed Touch Controllers:規定哪個手柄可以觸摸這個物體。
Ignored Colliders:對象上的碰撞數組在被觸摸時被忽略。
Grab Options 抓取設置
Is Grabbable:是否可以被抓起來。
Hold Button To Grab:如果勾選,則抓起對象時需要一直按着設置爲抓取的按鈕保持抓握狀態,如果沒勾選則按一下抓握按鈕就抓起來,再按一下釋放。
Stay Grabbed On Teleport:傳送時抓握的物體是否也跟着傳送。
Valid Drop:確定控制器抓取按鈕可以在什麼情況下丟下對象。NoDrop:什麼情況下控制器都無法丟下對象,DropAnywhere:控制器可以在任何情況下丟下對象,DropValidSnapDropZone:只有當對象懸停在有效的快速下拉區域上時,該對象才能被放下。
Grab Override Button:覆蓋手柄的抓取按鍵設置。
Allow Grab Controllers:規定哪個手柄可以抓握這個物體。
Grab Attach Mechanic Script:這可以確定被抓取的物品在被抓取時如何連接到控制器。 如果沒有提供,則將使用GameObject上的第一個Grab Attach腳本,如果沒有找到並且該對象可以被抓住,那麼將在運行時創建一個Fixed Joint Grab Attach腳本。
Secondary Grab Action Script:在輔助抓取時處理輔助控制器動作時使用的腳本。 如果沒有提供,則將使用GameObject上的第一個輔助控制器抓取操作腳本,如果沒有找到,則不會在輔助抓取上執行任何操作。
Use Options 使用設置
Is Usable:決定對象是否可以被使用。
Hold Button To Use:如果勾選,控制器上的使用(use)按鈕需要被持續按下來保持使用。如果沒有勾選,use按鈕用一次按鈕按下來啓動使用和再一次按下來停止使用。
Use Only If Grabbed:只有該物體被抓取時才能使用。
Pointer Activates Use Action:如果勾選,當一個世界光束指針(由控制器投射)碰到了交互對象,如果對象的Hold Button To Use沒有勾選的話,當指針在對象上的時候就會運行對象的StartUsing方法,指針移開失效就會運行StopUsing方法。這個選項在被勾選以後,就需要按住使用按鈕,爲了防止在用一個指針來使用對象時發生不必要的傳送,就不會拋出目標點設置( Destination Set )事件。
Use Override Button:自定義操作按鈕。
Allowed Use Controllers:允許使用的控制器。

上面提到了兩個新腳本VRTK_FixedJointGrabAttach和VRTK_SwapControllerGrabAction,正如上面所說對抓取有一定作用,請自行深入瞭解。



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章