차량을 2초간 바라보면 메뉴 UI를 보여줍니다.
메뉴가 열렸다면 메뉴를 응시 하면 게이지가 비워져야 합니다 (버튼 인터렉션을 위해)
다시 차량을 응시 했다면 메뉴가 열려 있기 때문에 게이지가 채워져 있어야 합니다.
예 버튼을 2초간 응시 했을경우 예를 선택 했습니다를 출력 합니다
아니오 버튼을 2초간 응시 했을 경우 아니오를 선택 했습니다를 출력 하고 메뉴를 닫습니다
* 콜라이더 설정 주의하기~~
차 - 콜라이더를 메뉴와 붙어있게 만들기
UI 메뉴 - 전체 사이즈 콜라이더 두께를 얇게 만들기
버튼 - 콜라이더 두께를 두껍게 만들기
플레이어 움직이기
- waypoint 설정하고 자연스럽게 회전하면서 움직이기
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public enum eMoveType
{
WayPoint,LookAt
}
public Transform[] waypoints;
public eMoveType moveType = eMoveType.WayPoint;
public float speed = 1.0f;
public float damping = 3.0f; //회전속도
public Transform trans; //내 위치
public int nextIdx = 1; //다음에 이동할 위치인덱스
public float range = 100.0f; // 시선이 닿는 범위
public bool isStopped;
void Start()
{
trans=GetComponent<Transform>();
waypoints = GameObject.Find("Waypoints").GetComponentsInChildren<Transform>();
}
void Update()
{
if (isStopped) return;
switch(moveType)
{
case eMoveType.WayPoint:
this.MoveWayPoint();
break;
case eMoveType.LookAt:
break;
}
}
private void MoveWayPoint()
{
//현재의 위치에서 다음 웨이포인트로 향하는 벡터 계산
Vector3 dir = this.waypoints[this.nextIdx].position- this.trans.position;
//벡터의 회전각도 계산
Quaternion rot = Quaternion.LookRotation(dir);
//현재각도에서 회전해야할 각도까지 부드럽게 회전 처리
this.trans.rotation = Quaternion.Slerp (this.trans.rotation, rot, Time.deltaTime*damping);
//전전 방향으로 이동
this.trans.Translate(Vector3.forward * Time.deltaTime * this.speed);
}
private void OnTriggerEnter(Collider other)
{
//웨이포인트에 충돌여부 판단
if (other.CompareTag("Waypoint"))
{
this.nextIdx = (++this.nextIdx >= this.waypoints.Length)?1:nextIdx;
}
}
}
보드판
- 카메라 방향에 따라 움직이기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Billboard : MonoBehaviour
{
private Transform camTrans;
private Transform trans;
void Start()
{
camTrans=Camera.main.GetComponent<Transform>();
trans=this.GetComponent<Transform>();
}
private void LateUpdate()
{
trans.LookAt(camTrans.position);
}
}
커스텀 게이지
- 응시하면 게이지가 채워짐
- 차를 응시하면 메뉴가 열림
- yes버튼을 응시하면 차량 정보가 열림
- no버튼을 응시하면 메뉴가 닫힘
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EyeCast : MonoBehaviour
{
[SerializeField] private float distance = 10f;
[SerializeField] private float maxTimeToOpenUIMenu = 2f;
bool isOpenedUIMenu = false;
public System.Action onOpenUIMenu;
public System.Action onCloseUIMenu;
public Image gauge;
private Coroutine coroutine;
public bool isLookatButtonYes = false;
public bool isLookatButtonNo = false;
private Player player;
// 변수 추가
private bool isLookingAtButton = false;
private void Start()
{
player = FindAnyObjectByType<Player>();
}
// Update 함수 수정
void Update()
{
var ray = new Ray(this.transform.position, this.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * distance, Color.red);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, distance, 1 << 6 | 1 << 5| 1 << 7))
{
player.isStopped = true;
if (hit.collider.gameObject.name == "Menu")
{
// Debug.Log($"메뉴를 보고있습니다.");
this.isLookingAtButton = false;
this.gauge.fillAmount = 0;
}
else if (hit.collider.gameObject.name == "Car_B1")
{
if (isOpenedUIMenu == false)
{
//Debug.Log("UIMenu를 보여준다");
isOpenedUIMenu = true;
if (this.coroutine != null)
StopCoroutine(this.coroutine);
this.coroutine = StartCoroutine(this.CoWaitForOpenUIMenu());
}
else
{
this.gauge.fillAmount = 1;
}
}
else if (hit.collider.gameObject.name == "btnYes")
{
if (!isLookingAtButton) // 버튼을 처음 응시할 때만 실행
{
isLookingAtButton = true;
Debug.Log("btnYes응시 시작");
if (this.coroutine != null)
StopCoroutine(this.coroutine);
this.coroutine = StartCoroutine(this.CoWaitForBtnYes());
}
}
else if (hit.collider.gameObject.name == "btnNo")
{
if (!isLookingAtButton) // 버튼을 처음 응시할 때만 실행
{
isLookingAtButton = true;
Debug.Log("btnNo응시 시작");
if (this.coroutine != null)
StopCoroutine(this.coroutine);
this.coroutine = StartCoroutine(this.CoWaitForBtnNo());
}
}
}
else
{
if (isOpenedUIMenu)
{
isOpenedUIMenu = false;
//Debug.Log("UIMenu를 안보여준다");
if (coroutine != null)
{
this.gauge.fillAmount = 0;
this.StopCoroutine(this.coroutine);
}
this.onCloseUIMenu();
}
// 버튼을 응시하고 있지 않음을 감지하고 변수 재설정
isLookingAtButton = false;
player.isStopped = false;
}
}
// 버튼 응시 코루틴 함수 수정
private IEnumerator CoWaitForBtnYes()
{
float delta = 0f;
while (true)
{
if (!isLookingAtButton) // 응시가 중단되면 반복문 탈출
break;
delta += Time.deltaTime;
float fillAmount = delta / maxTimeToOpenUIMenu;
this.gauge.fillAmount = fillAmount;
if (delta >= maxTimeToOpenUIMenu)
{
break;
}
yield return null;
}
if (isLookingAtButton) // 버튼을 계속 응시하는 동안만 실행
{
Debug.Log($"<color=yellow>차량의 정보를 보여줍니다.</color>");
}
}
private IEnumerator CoWaitForBtnNo()
{
float delta = 0f;
while (true)
{
if (!isLookingAtButton) // 응시가 중단되면 반복문 탈출
break;
delta += Time.deltaTime;
float fillAmount = delta / maxTimeToOpenUIMenu;
this.gauge.fillAmount = fillAmount;
if (delta >= maxTimeToOpenUIMenu)
{
break;
}
yield return null;
}
if (isLookingAtButton) // 버튼을 계속 응시하는 동안만 실행
{
Debug.Log($"<color=yellow>아니오를 선택 했습니다.</color>");
this.gauge.fillAmount = 0;
this.onCloseUIMenu();
}
}
private IEnumerator CoWaitForOpenUIMenu()
{
float delta = 0f;
while (true)
{
delta += Time.deltaTime;
float fillAmount = delta / maxTimeToOpenUIMenu;
this.gauge.fillAmount = fillAmount;
if (delta >= maxTimeToOpenUIMenu)
{
break;
}
yield return null;
}
this.onOpenUIMenu();
}
}
메인
- UI 활성화 비활성화 설정
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Main : MonoBehaviour
{
public GameObject menuCanvasGo;
public EyeCast eyeCast;
void Start()
{
eyeCast.onOpenUIMenu = () => {
OpenUIMenu();
};
eyeCast.onCloseUIMenu = () => {
CloseUIMenu();
};
}
private void OpenUIMenu()
{
this.menuCanvasGo.SetActive(true);
}
private void CloseUIMenu()
{
this.menuCanvasGo.SetActive(false);
}
}
'게임개발 > VR 콘텐츠 기초 및 구현' 카테고리의 다른 글
Ghost (0) | 2024.04.18 |
---|---|
Oculus 기본 설정 (0) | 2024.04.18 |