본문 바로가기
[Unity]

[Unity] Camera를 사용하여 World Canvas에 이벤트 전달하기

by 김기승 2020. 2. 10.

VR 콘텐츠를 재생할 때, HMD를 착용하고 조이스틱에서 나오는 레이저 포인터를 사용하여 UI를 조작한다.

이 레이저 포인터를 구현하기 위해 학습한 기법을 소개하고자 한다.

 

본래 Canvas는 마우스 커서로 이벤트(클릭, 호버링 등)를 전달받을 수 있다. 그러나 마우스가 아닌 다른 방법으로 Canvas에 이벤트를 전달해본 경험은 드물 것이다.

 

이 기법을 활용하기 위해서는 이벤트 발생 방법에 대한 대략적인 이해가 필요하다. 카메라 상의 마우스의 좌표는 PointerEventData가 담고, 이 좌표로부터 GraphicRaycaster가 발생한다. GraphicRaycaster가 UI와 충돌하면, 충돌한 UI는 BaseInputModule 클래스에 있는 함수들로 이벤트를 전달받는다.

 

캔버스와 GraphicRaycaster를 발생시킬 카메라를 생성해주었다. 또한, 위 그림처럼 Event Camera를 지정해주어야 한다.

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; //GraphicRaycaster 사용하기 위한 지시문

public class GraphicRaycasterEX : BaseInputModule //BaseInputModule 클래스 상속
{
    public GraphicRaycaster graphicRaycaster; //Canvas에 있는 GraphicRaycaster
    private List<RaycastResult> raycastResults; //Raycast로 충돌한 UI들을 담는 리스트
    private PointerEventData pointerEventData; //Canvas 상의 포인터 위치 및 정보
    public Camera target; //마우스 커서 역할을 대신할 카메라

    protected override void Start()
    {
        pointerEventData = new PointerEventData(null); //pointerEventData 초기화
        pointerEventData.position = new Vector2(target.pixelWidth * 0.5f, target.pixelHeight * 0.5f); //카메라의 중앙으로 포인터 지정
        raycastResults = new List<RaycastResult>(); //리스트 초기화
    }

    private void Update()
    {
        graphicRaycaster.Raycast(pointerEventData, raycastResults); //포인터 위치로부터 Raycast 발생, 결과는 raycastResults에 담긴다

        if (raycastResults.Count > 0) //충돌한 UI가 있으면
        {
            foreach (RaycastResult raycastResult in raycastResults) //충돌한 UI 탐색
            {
                HandlePointerExitAndEnter(pointerEventData, raycastResult.gameObject); //호버링 이벤트 전달
                if (Input.GetKeyDown(KeyCode.Space)) //임의의 버튼을 클릭하면
                    ExecuteEvents.Execute(raycastResult.gameObject, new BaseEventData(eventSystem), ExecuteEvents.submitHandler); //해당 UI에 클릭 이벤트 전달
            }
        }
        else //충돌한 UI가 없으면
        {
            HandlePointerExitAndEnter(pointerEventData, null); //포인터 벗어남 → GameObject가 null이어야 호버링에서 벗어남
        }

        raycastResults.Clear(); //Raycast 결과 리스트 초기화 → 필수
    }

    public override void Process() { } //상속받아야 에러 안뜸
    protected override void OnEnable() { } //상속받아야 에러 안뜸
    protected override void OnDisable() { } //상속받아야 에러 안뜸
}

GrapicRaycasterEX 스크립트를 생성해주고, 본 내용처럼 작성하였다. 잘 보면 BaseInputModule 클래스를 상속받았다.

 

다음과 같이 카메라가 바라보는 UI에 호버링이 발생하는 것을 볼 수 있다. 또한, 스크립트에서 작성한 스페이스 바를 클릭하여 클릭 이벤트를 발생시킨다.


본 기법을 사용하면 VR 조이스틱에 부착된 Camera가 여러 UI를 다룰 수 있을 것으로 보인다.

여러 외국 사이트들을 돌아다니면서 종합된 내용을 토대로 작성한 것이라 근본이 없을 수 있으나, 조금이나마 도움이 되었으면 한다.

댓글