VR 핸드 시계 와 UI 메뉴

VR/XR Interaction Toolkit 2024. 1. 10. 13:59
반응형

 

https://youtu.be/CDrSGeiA1a8?list=PLTFRwWXfOIYBIPKhWi-ZO_ITXqtNuqj6j

손등을 바라보면 시계가 나오는 기능 만들기 

 

내적을 사용해 바라보는 방향과 손목의 방향을 계산후 일정 각도 이하면 UI를 보여줍니다.

 

ControllerHand스크립트를 생성하고 Left Controller에 부착후 다음과 같이 작성 합니다.

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using TMPro;
public class ControllerHand : MonoBehaviour
{
    [SerializeField] private Transform palm;
    [SerializeField] private Transform centerEye;
    [SerializeField] private TMP_Text txtAngle;

    [SerializeField] private GameObject ui;
    void Start()
    {
        
    }

    private void Update()
    {
        this.DrawPalmRay();
        this.DrawWorldForwardRay();

        var angle = this.CalcAngle();
        this.DisplayUI(angle);
    }

    private void DisplayUI(float angle)
    {
        if (angle <= 20)
        {
            ActiveUI();
        }
        else
        {
            DeactiveUI();
        }
    }

    private void ActiveUI()
    {
        ui.SetActive(true);
    }

    private void DeactiveUI()
    {
        ui.SetActive(false);
    }

    private float CalcAngle()
    {
        var dot = Vector3.Dot(-centerEye.forward, -palm.right);
        var angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
        txtAngle.text = angle.ToString("0.00");
        return angle;
    }

    private void DrawWorldForwardRay()
    {
        var ray = new Ray(palm.transform.position, -centerEye.forward);
        //Debug.DrawRay(ray.origin, ray.direction, Color.blue, 0);
        DrawArrow.ForDebug(ray.origin, ray.direction, 0, Color.blue, ArrowType.Default);
    }

    private void DrawPalmRay()
    {
        var ray = new Ray(palm.transform.position, -palm.right);
        DrawArrow.ForDebug(ray.origin, ray.direction, 0, Color.red, ArrowType.Default);
        //Debug.DrawRay(ray.origin, ray.direction, Color.red, 0);
    }
}

 

 

UI구성 하기 

UI는 시 분 초로 보여주고 날짜와 오전/오후 표시를 위해 여러개의 텍스를 사용합니다.

using UnityEngine;
using TMPro;

public class DigitalClock : MonoBehaviour
{
    [SerializeField] private TMP_Text h0;
    [SerializeField] private TMP_Text h1;
    [SerializeField] private TMP_Text m0;
    [SerializeField] private TMP_Text m1;
    [SerializeField] private TMP_Text s0;
    [SerializeField] private TMP_Text s1;
    
    [SerializeField] private TMP_Text d0;
    [SerializeField] private TMP_Text d1;
    [SerializeField] private TMP_Text month0;
    [SerializeField] private TMP_Text month1;
    [SerializeField] private TMP_Text y0;
    [SerializeField] private TMP_Text y1;
    
    [SerializeField] private TMP_Text ampm;
    private bool use12HourFormat = true; // 12시간 형식 사용 여부
    
    void Start()
    {
        
    }

     void Update()
    {
        // 현재 시간을 얻어옵니다.
        System.DateTime currentTime = System.DateTime.Now;

        // 시, 분, 초를 따로 얻어옵니다.
        int hour = currentTime.Hour;
        int minute = currentTime.Minute;
        int second = currentTime.Second;

        // AM 또는 PM을 가져오는 메서드
        string amPm = GetAmPm(hour);

        // 시간을 12시간 또는 24시간 형식으로 포맷팅합니다.
        string formattedHour = use12HourFormat ? Format12Hour(hour) : hour.ToString("D2");

        // 시간, 분, 초를 두 자리 숫자로 포맷팅합니다.
        string formattedTime = string.Format("{0}:{1:D2}:{2:D2} {3}", formattedHour, minute, second, amPm);

        // 현재 날짜를 가져옵니다.
        int year = GetYear(currentTime);
        int month = GetMonth(currentTime);
        int day = GetDay(currentTime);
        
        var strHour = string.Format("{0:D2}", hour);
        h0.text = strHour[0].ToString();
        h1.text = strHour[1].ToString();
        
        var strMin = string.Format("{0:D2}", minute);
        m0.text = strMin[0].ToString();
        m1.text = strMin[1].ToString();
        
        var strSec = string.Format("{0:D2}", second);
        s0.text = strSec[0].ToString();
        s1.text = strSec[1].ToString();
        
        var strYear = string.Format("{0:D2}", year);
        y0.text = strYear[2].ToString();
        y1.text = strYear[3].ToString();
        
        var strMonth = string.Format("{0:D2}", month);
        month0.text = strMonth[0].ToString();
        month1.text = strMonth[1].ToString();
        
        var strDay = string.Format("{0:D2}", day);
        d0.text = strDay[0].ToString();
        d1.text = strDay[1].ToString();

        ampm.text = GetAmPm(hour);
    }

    // AM 또는 PM을 가져오는 메서드
    string GetAmPm(int hour)
    {
        return hour >= 12 ? "PM" : "AM";
    }

    // 12시간 형식으로 시간을 포맷팅하는 메서드
    string Format12Hour(int hour)
    {
        if (hour == 0)
        {
            return "12";
        }
        else if (hour > 12)
        {
            return (hour - 12).ToString("D2");
        }
        else
        {
            return hour.ToString("D2");
        }
    }

    // 년도를 가져오는 메서드
    int GetYear(System.DateTime dateTime)
    {
        return dateTime.Year;
    }

    // 월을 가져오는 메서드
    int GetMonth(System.DateTime dateTime)
    {
        return dateTime.Month;
    }

    // 일을 가져오는 메서드
    int GetDay(System.DateTime dateTime)
    {
        return dateTime.Day;
    }
}

 

사용된 리소스 폰트 에셋 

digital-7.zip
0.04MB

 

 

 


참고 자료 

https://learn.microsoft.com/ko-kr/windows/mixed-reality/design/hand-menu

 

손 메뉴 - Mixed Reality

손 메뉴를 사용하면 자주 사용되는 함수에 대한 손 연결 UI를 빠르게 가져올 수 있습니다.

learn.microsoft.com

 

반응형
: