프로그래밍/Unity

Unity XR Toolkit을 이용한 VR Input 설정 방법

Lou Park 2021. 9. 4. 20:06

XR = AR + VR


[1] XR Interaction Toolkit 설치

[Window > Package Manager > Advanced > Show preview packages]

XR Interaction Toolkit을 다운로드한다.

 

[2] XR Plugin Management 설정

[Edit > Project Settings >  XR Plugin Management]

Import XR Plugin Management 클릭

컴퓨터 모양에서 Oculus / Windows Mixed Reality 체크

안드로이드 모양에서 Oculus 체크

 

[3] 시선 XR Rig 설정

GameObject 생성 후 "XR Rig"라고 네이밍,  XR Rig Component를 추가해준다.

XR Rig GameObject 자식으로 "Camera Offset"이라는 GameObject 생성, 그 안에는 Camera를 생성한다.

Camera가 VR 헤드셋 시선을 따라가기 위해 Tracked Pose Driver Component를 추가한다.

그리고 Camera Component에 Clipping Planes > Near 값을 0.1 정도로 줄여주면, 가까이에있는 폴리곤을 시선이 뚫어서 투명으로 비치는 거리를 줄일 수 있다.

마지막으로 XR Rig GameObject > XR Rig Component의

Camera Floor Offset Object: Camera Offset GameObject

Camera GameObject: Camera GameObject를 연결시켜준다.

그리고 Tracking Origin Mode를 Floor로 설정해주어야 키 만큼의 높이가 설정이 된다.

 

[4] 왼손, 오른손 설정

Camera Offset GameObject의 자식으로 Left Hand, Right Hand GameObject를 생성한다.

각각에 XR Controller Component (Device-based)를 추가한다.

Controller Node 역시 각각 L/R Hand를 설정한다.

XR Controller Component의 Model prefab은 손을 표현하는 Prefab을 넣어주면 비주얼이 보인다.


잡을 수 있는 물체

잡을 수 있는 물체에는 XR Grab Interactable Component를 추가해야한다.

손은 잡기위해서 양쪽 손의 GameObject에 모두 XR Direct Interactor를 추가한다.

그리고 충돌을 감지하기 위해 Sphere Collider도 추가한다. Radius: 0.2, Is Trigger: True

 

Input Debugging 

현재 어느 버튼이 눌리고있는지 디버거를 통해 확인하려면

[Window > Analysis > XR Interavtion Debugger]를 켜면된다.

 

Input Devices 가져오기

using UnityEngine.XR;

public class SomeScript : MonoBehaviour
{
    void Start()
    {
        // 머리, 양손의 컨트롤러 모두에 접근하는 방법
        List<InputDevice> devices = new List<InputDevice>();
        InputDevices.GetDevices(devices);

        // 특정 컨트롤러하나만 가져오는 방법
        InputDeviceCharacteristics rightControllerCharacteristics =
            InputDeviceCharacteristics.Right | InputDeviceCharacteristics.Controller;
        InputDevices.GetDevicesWithCharacteristics(rightControllerCharacteristics, devices);

        foreach (var item in devices)
        {
        	// example) item.name: Oculus Touch Controller - Left
            Debug.Log(item.name + item.characteristics);
        }
    }
}

Input Devices로부터 입력 가져오기

Update() 부분의 코드를 보면된다. 

using UnityEngine.XR;

public class SomeScript : MonoBehaviour
{
    private InputDevice targetDevice;

    void Start()
    {
        // 특정 컨트롤러하나만 가져오는 방법
        List<InputDevice> devices = new List<InputDevice>();
        InputDeviceCharacteristics rightControllerCharacteristics =
            InputDeviceCharacteristics.Right | InputDeviceCharacteristics.Controller;
        InputDevices.GetDevicesWithCharacteristics(rightControllerCharacteristics, devices);

        if (devices.Count > 0)
        	targetDevice = devices[0];
    }

    void Update()
    {
        /**
         * Boolean: 버튼 누른 여부
         * Float: Axis Range 0 ~ 1
         * Vector2: Touchpad 움직임 -1 ~ 1
         */
        targetDevice.TryGetFeatureValue(CommonUsages.primaryButton, out bool primaryButtonValue);
        if (primaryButtonValue)
        	Debug.Log("Pressing primary button");

        targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue);
        if (triggerValue > 0.1F)
        	Debug.Log("Trigger pressed " + triggerValue);
            

        targetDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 primary2DAxisValue);
        if (primary2DAxisValue != Vector2.zero)
        	Debug.Log("Primary Touchpad " + primary2DAxisValue);
    }
}

 

컨트롤러 각 버튼에 대한 CommonUsages 매핑자료

사진은 Oculus Quest2 기준으로 가지고 왔다.

Button.One = Primary, Button.Two = Secondary

 

 

당장 테스트 해볼 수 있는 Hand Controller Asset Download Link

여기서 unitypackage 다운받아서 쓰면된다.

다양한 컨트롤러가 있는 package

손 밖에 없는 package

 

동적으로 Controller Prefab 할당하기

손 모양에서 컨트롤러 모양으로 바꾸거나,  기타 등등 동적으로 컨트롤러 Prefab을 바꿔주어야 할 때가 있다.

빈 Prefab을 만들고, HandPresence(이름은 상관없음)라는 스크립트를 붙인다.  public field로 GameObject 하나를 설정하고, 어떤 조건에따라 Prefab을 Instantiate 해주면 된다. 그리고 HandPresence 스크립트가 붙은 Prefab을 XR Controller Component의 Model prefab로 지정해주면 된다.

public class HandPresence : MonoBehaviour
{
    
    // 플레이어 눈에 보이는 게임오브젝트
    private GameObject spawnedController; 

    public GameObject prefab;
    public GameObject prefab2;

    void Start() 
    {
        if (someConditionIsTrue) 
        {
            spawnedController = Instantiate(prefab, transform)
        } 
        else 
        {
            spawnedController = Instantiate(prefab2, transform)
        }
    }
}

참고 영상

https://www.youtube.com/watch?v=gGYtahQjmWQ&list=PLrk7hDwk64-a_gf7mBBduQb3PEBYnG4fU&index=2