VR 컨트롤러 만들기 – 쳐다만 봐도 콘텐츠 선택되는 기능 만들기
마그네틱 스위치를 이용해서 메뉴 선택이나 확인 버튼으로 이용할 수 있으나 마그네틱 스위치가 없을 경우 가장 기본적으로 적용할 수 있는 스위치 방법이 일정 시간동안 오브젝트를 바라 보았을 때, 오브젝트가 선택되는 방식을 기본적으로 이용할 수 있습니다.
따라서, 이번 강의에서는 일정 시간동안 오브젝트를 바라 보았을때 동작하는 기능을 만들어 보겠습니다.
이전 예제에서 이용한 BoxCtrl과 RayCast 개념을 그대로 사용하고, 여기에 타이머를 추가하여 응용할 수 있습니다.
하이어라키 창에서 오른쪽 클릭 -> 3D Object -> Sphere로 구를 추가합니다.
이 구에 BoxCtrl 스크립트를 그대로 추가합니다.
Tag는 Ball을 추가하여 설정합니다.
마그네틱 스위치 인식과 오브젝트 선택 기억나지 않으면 아래 링크를 참고 합니다.
프리팹으로 만든 후 여러 개 적당한 위치에 배치 해 봅시다.
using UnityEngine;
using System.Collections;
public class TriggerTextCtrl : MonoBehaviour {
//결합할 텍스트 상수입니다.
private const string TEXT = "Count : ";
//접근 제어자를 public으로 하면 유니티 에디터에서 이 변수를 설정할 수 있습니다.
public Cardboard cardBoard;
//3DText의 글자는 TextMesh 컴포넌트에서 변경했기 때문에 TextMesh 컴포넌트를 가져와야 합니다.
private TextMesh textMesh;
//카운트 변수입니다.
private int count = 0;
//Update 메소드가 호출되기 전 단 한 번 호출 됩니다. 보통 변수들을 초기화 하는것을 여기에다 작성합니다.
private Vector3 screenCenter;
//몇 초간 바라보는 것으로 설정할 것인지에 대한 변수입니다. 에디터에서 수정가능하도록 했습니다.
public float durTime = 3f;
// 쳐다보고 있는 오브젝트가 저장됩니다.
public GameObject recentObject;
// 쳐다보기 시작한 시간을 저장합니다.
private float startTime;
void Start()
{
//gameObject에는 본 컴포넌트가 추가된 게임 오브젝트가 들어가 있습니다. GetComponent<가져올 컴포넌트>(); 를 이용하면 컴포넌트를 가져올 수 있습니다.
textMesh = gameObject.GetComponent<TextMesh>();
screenCenter = new Vector3(Camera.main.pixelWidth / 2, Camera.main.pixelHeight / 2);
}
//매 프레임마다 호출되는 메소드 입니다. 여기서 게임 오브젝트의 변화를 설정합니다.
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(screenCenter);
RaycastHit hit;
//레이저가 공을 맞췄는지에 대한 불리언 값입니다.
bool isRayHitBox = Physics.Raycast(ray, out hit, 500f) && hit.collider.gameObject.tag == "Ball";
if (isRayHitBox)
{
//최근 쳐다본 오브젝트가 비어있지 않고, 지금 레이저에 맞은 오브젝트와 같은지 여부를 불리언 값으로 저장합니다.
bool isRecentObjEqualsCollObj = recentObject != null && recentObject.gameObject.Equals(hit.collider.gameObject);
if (startTime + durTime < Time.time)
{
BoxCtrl ctrl = hit.collider.gameObject.GetComponent<BoxCtrl>();
ctrl.Select();
}
else
{
recentObject = hit.collider.gameObject;
startTime = Time.time;
}
}
else
{
recentObject = null;
}
//카드보드에서 Triggered Getter는 트리거가 발생했는지 알 수 있습니다.
if (cardBoard.Triggered)
{
//박스에 초점이고
if (Physics.Raycast(ray, out hit, 500f))
{
if (hit.collider.gameObject.tag == "Box")
{
BoxCtrl boxCtrl = hit.collider.gameObject.GetComponent<BoxCtrl>();
boxCtrl.Select();
//TextMesh 컴포넌트의 text를 변경합니다.
count++;
textMesh.text = TEXT + count.ToString();
}
}
}
}
}
//TriggerTextCtrl 스크립트를 그대로 사용합니다.
//위 처럼 코드를 추가 해 주세요.
//추가 된 부분을 설명 하겠습니다.
// 몇 초간 바라보는 것으로 설정할 것인지에 대한 변수입니다. 에디터에서 수정가능하도록 했습니다.
public float durTime = 3f;
// 쳐다보고 있는 오브젝트가 저장됩니다.
public GameObject recentObject;
// 쳐다보기 시작한 시간을 저장합니다.
private float startTime;
bool isRayHitBox = Physics.Raycast(ray, out hit, 500f) && hit.collider.gameObject.tag == "Ball";
//레이저가 공을 맞췄는지에 대한 불리언 값입니다.
bool isRecentObjEqualsCollObj = recentObject != null && recentObject.gameObject.Equals(hit.collider.gameObject);
//최근 쳐다본 오브젝트가 비어있지 않고, 지금 레이저에 맞은 오브젝트와 같은지 여부를 불리언 값으로 저장합니다.
if (startTime + durTime < Time.time)
{
BoxCtrl ctrl = hit.collider.gameObject.GetComponent<BoxCtrl>();
ctrl.Select();
}
//Time.time은 게임이 시작된 후 경과된 시간이 저장되어 있습니다. 보기 시작한 시간과 바라 볼 시간을 더한 값이 경과 시간보다 작아질 경우, 그러니까 durTime만큼 시간이 지나면 오브젝트에서 BoxCtrl 컴포넌트를 얻어 색을 변경합니다.
else
{
recentObject = hit.collider.gameObject;
startTime = Time.time;
}
//최근 쳐다본 오브젝트가 비어있지 않고, 지금 레이저에 맞은 오브젝트가 같지 않다면 지금 쳐다보고 있는 오브젝트로 변경 해 주고, 시작 시간을 다시 초기화 합니다.
else
{
recentObject = null;
}