본문 바로가기
VR/기본기

VR 마우스 구현 - UI와 상호작용하기

by TODAYCODE 2021. 6. 3.
반응형

VR은 PC와 환경이 참 많이 다르다.

PC 환경에서는 UI 버튼이 존재하면 그냥 마우스로 클릭하면 되는데

VR에서는 마우스가 없고 마우스와 비슷한 걸 만들더라도,

클릭이나 버튼을 인식하는 방식을 PC와는 다르게 구현해야한다.

 

 

VR에서 UI와 상호작용을 가능하게 하는 방법은 정말 다양하다.

 

여기서는 그냥 내가 주로 사용하는 방법을 적을 예정이다.

아마 내가 사용하는 방법이 번거롭고 불편할 수도 있다.

사람에 따라서 본인에게 맞는 방법을 찾도록 노력하면 될 것.

 

오늘 소개할 스크립트는 내가 VR 상에서 UI 상호작용이 필요하면 계속해서 꺼내서 사용하는 스크립트이다.


먼저 아래 코드들이 스크립트 내용이고 하나씩 살펴보도록 하자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class VRUIRay : MonoBehaviour
{
	// 1. 우선 해당 스크립트를 싱글톤으로 만들었다.
    public static VRUIRay instance;
    
    
    // 2. 마우스 역할을 수행할 게임오브젝트를 준비한다.
    // VR 오른쪽 컨트롤러
    public Transform rightHand;
    // 마우스 포인터를 대체할 이미지
    public Transform dot;

    private void Awake()
    {
        instance = this;
    }

    void Update()
    {
    	// 3. Ray를 사용해서 dot(마우스포인터)를 활성화한다.
        Ray ray = new Ray(rightHand.position, rightHand.forward);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit))
        {
            if (hit.transform.gameObject.layer == LayerMask.NameToLayer("UI"))
            {
                dot.gameObject.SetActive(true);
                dot.position = hit.point;
            }
            else
            {
                dot.gameObject.SetActive(false);
            }
            
            
            // 4. dot이 충돌 중 일 때 클릭할 수 있도록 한다.
            // 만약 점이 활성화 상태면
            if (dot.gameObject.activeSelf)
            {
                if (OVRInput.GetDown(OVRInput.Button.Any))
                {
                    // 버튼 스크립트를 가져온다
                    Button btn = hit.transform.GetComponent<Button>();
                    // 만약 btn이 null이 아니라면
                    if (btn != null)
                    {
                        btn.onClick.Invoke();
                    }
                }
            }
        }
        else
        {
            dot.gameObject.SetActive(false);
        }
    }
}

1. 우선 해당 스크립트를 싱글톤으로 만들었다.

그 이유는 나중에 다양한 상호작용을 발생시킬 때 편하게 하기 위함인데,

이는 다음번에 설명하도록 하겠다.

아무튼, 나중에 편하기 위해서 그렇게 했다.

 

 

2. 마우스 역할을 수행할 게임오브젝트를 준비한다.

마우스의 역할을 수행할 VR 컨트롤러와 dot(마우스 포인터 역할)이 필요했기에,

public을 선언했고 유니티 상에서 연결해 줬다.

 

 

3. Ray를 사용해서 dot(마우스포인터)를 활성화한다.

Update 내부에 Ray 관련 코드를 적었다.

VR컨트롤러에서 앞방향으로 발사하는 Ray를 생성했고,

Ray가 충돌하는 오브젝트를 담아오도록 Raycast hit을 써줬다.

그러면 이제 hit 에 ray에 충돌한 오브젝트의 정보가 담긴다.

 

만약 충돌한 오브젝트의 레이어가 UI라면

( = hit에 담겨있는 오브젝트의 레이어가 UI 라면 )

 

맨처음 받아왔던 마우스포인터 역할인 dot을 활성화시켜서

Ray가 충돌하고 있는 위치로 옮겨준다.

 

이렇게 하면 평소에는 dot(마우스포인터)는 보이지 않다가

ray가 ui에 충돌했을 때만 dot(마우스포인터)가 나타난다.

 

조건문을 통해 ray가 충돌한 오브젝트의 레어어가 UI가 아니게 된다면 dot의 활성을 껐다

 

 

 

4. dot이 충돌 중 일 때 클릭할 수 있도록 한다.

위에서 이미 설정해뒀기 때문에,

dot이 활성화 되었을 때는 UI에 ray가 충돌 중일 때 뿐이다.

조건문을 사용해서 dot이 활성화 되어있을 때만

클릭기능이 인식되도록 한다.

스크립트에서는 그냥 아무키나 눌러도 되도록 했다.

 

만약, 클릭을 했다면

ray가 충돌중인 UI가 가지고 있는 버튼을 가져온다.

물론, 충돌 중인 UI가 버튼이 아닐수도 있다.

그래도 상관없이 일단 가져오게 한다.

 

선택된 UI가 버튼이라면 해당 정보가 담겼을 것이고,

버튼이 아니었다면 버튼 정보가 null값으로 존재할 것이다.

 

여기서 다시 조건문을 사용해서,

버튼이 null이 아니면,

버튼에 담겨있는 함수를 실행하도록 한다.

 

이러면 버튼일 경우에는 클릭했을 때처럼 버튼에 담겼던 함수가 동작하고,

버튼이 아니면 아무일도 발생하지 않는다.

 

 

 

5. 버튼이 아닌 UI와 상호작용하는 법.

 

위에서 클릭했을 때 버튼정보를 담아오도록 코드를 작성했는데,

이걸 버튼이 아니라,

InputField나 다른 UI들로 적어서 정보를 받을 수 있게 하고,

null 아닐 때 동작하도록 똑같이 만들어준다면

버튼이 아닌 UI들과도 상호작용할 수 있게 된다.

 

 

 

※ 끝으로,

VR에서 UI와 상호작용하기 위해서는

UI에 collider 컴포넌트를 추가해서 Ray에 충돌이 되도록 해줘야한다.

UI에 Collider를 넣고 콜라이더 크기를 ui크기에 맞게 설정해야한다.

그렇지 않으면 인식할 수 없다

반응형

'VR > 기본기' 카테고리의 다른 글

VR 가상키보드 사용하기 : VRKB  (0) 2021.06.04
유니티에서 오큘러스 VR 세팅하기  (2) 2021.05.31

댓글