본문 바로가기
게임개발/VR 콘텐츠 기초 및 구현

커스텀 게이지

by pudding81 2024. 4. 15.

차량을 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