본문 바로가기
개발/Unity

(1) 중심 게이지 만들기 - 파이 메뉴(Pie / Radial Menu) 만들기

by 피로물든딸기 2022. 5. 8.
반응형

Unity 전체 링크

 

파이 메뉴 만들기 (Pie / Radial Menu)

 

(1) 중심 게이지 만들기

(2) 버튼 만들기

(3) Tooltip 만들기

(4) Text 자동 크기 조절

(5) 버튼 배치하기

(6) 버튼에 이벤트 연결하기


아래와 같은 블렌더의 파이 메뉴 UI를 유니티에서 만들어보자.

 

아래 png를 다운 받아서 스프라이트로 만들자. 

그대로 쓰면 중심이 어긋나 있기 때문에 스프라이트를 잘라줘야 한다.

 

Sprite를 잘랐으면 Canvas 아래에 Empty(PieMenu) Image 2개(FullGauge, Gauge)를 만든다. 

FullGauge는 Color를 검은색으로 변경한다.

 

Gauge는 Image Type을 Filled로 변경한 후, Fill Amount를 적절히 변경한다.

 

그러면 게임화면에 아래와 같은 화면이 보이게 된다.

 

Gauge.cs 스크립트를 Gauge 이미지에 추가한 후, 아래와 같이 코드를 추가한다.

transform의 childCount에서 자식 오브젝트의 개수를 알 수 있다.

따라서 Gauge 아래의 하위 메뉴에 따라 fillAmount를 children의 개수로 나누어 주면 칸을 나눌 수 있다.

    Image gauge;

    void Start()
    {
        gauge = this.GetComponent<Image>();

        int numOfChild = this.transform.childCount;

        gauge.fillAmount = 1.0f / numOfChild;
    }

 

아래와 같이 메뉴가 3개인 경우 3개로 등분되며, 메뉴가 7개인 경우는 7개로 나뉘어지는 것을 볼 수 있다.

여기서 Menu는 나중에 PieMenu에 필요한 Button이 된다.

 

이제 Gauge를 마우스 방향으로 회전시켜보자.

Atan2 함수를 탄젠트 값을 이용하여 각도를 구하는 함수다.

현재 Image의 좌표와 마우스의 좌표의 각도를 구해 AngleAxis를 이용해 회전한다.

Mathf.Rad2Deg는 radian(2pi)를 degree(180º)로 변환할 때 필요한 상수다.

    Image gauge;
    Vector2 position;
    
    void Start()
    {
        position = this.transform.position;
        ...
    }

    void Update()
    {
        float angle = Mathf.Atan2(
            Input.mousePosition.y - position.y, Input.mousePosition.x - position.x) 
            * Mathf.Rad2Deg; /* radian -> degree */
        this.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }

(UI와 Input.mousePosition 모두 Screen의 좌표이기 때문에 따로 변환이 필요없다.)

 

마우스가 움직이는 대로 회전은 하지만, 게이지가 마우스를 향하지는 않는다.

아래와 같이 마우스가 이미지의 중심에서 정확히 왼쪽에 있을 때가 0º 가 된다.

따라서 보정이 필요하다.

 

먼저 게이지가 차지하는 각도를 세타(Θ)라고 하자.

 

그러면 게이지는 아래와 같이 Θ의 절반인 Θ / 2가 마우스를 향하게 해야 한다.

 

그리고 마우스가 오브젝트의 왼쪽에 있을 때, 0º이므로 90º와 Θ / 2를 보정하면 된다.

Θ는 360에서 메뉴의 개수로 나누면 된다.

theta 변수를 추가한 후, angle에 90 + Θ / 2를 보정하였다.

    Image gauge;
    Vector2 position;
    float theta;

    void Start()
    {
        ...
        
        theta = 360.0f / numOfChild;
    }

    void Update()
    {
        float angle = Mathf.Atan2(
            Input.mousePosition.y - position.y, Input.mousePosition.x - position.x) 
            * Mathf.Rad2Deg /* radian -> degree */
            + 90.0f + (theta / 2.0f); /* 보정 */
        this.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }

 

Menu의 개수에 따라 Gauge의 fillAmount가 변경되고, 마우스를 제대로 향하는 것을 알 수 있다.

 

전체 코드는 아래와 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Gauge : MonoBehaviour
{
    Image gauge;
    Vector2 position;
    float theta;

    void Start()
    {
        position = this.transform.position;
        gauge = this.GetComponent<Image>();

        int numOfChild = this.transform.childCount;

        gauge.fillAmount = 1.0f / numOfChild;
        theta = 360.0f / numOfChild;
    }

    void Update()
    {
        float angle = Mathf.Atan2(
            Input.mousePosition.y - position.y, Input.mousePosition.x - position.x) 
            * Mathf.Rad2Deg /* radian -> degree */
            + 90.0f + (theta / 2.0f); /* 보정 */
        this.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }
}

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글