728x90



 

원하는 거: 그냥 단순히.. 슬라이더를 원형으로 하고 싶었고 핸들을 잡고 직접 돌리고 싶다.

아래 사진 참고.

 

검은 점을 잡고 돌리는 슬라이더

 

내가 원하는 건 위 사진의 검은 점을 잡고 원형으로 돌렸을때, 그 위치를 따라오면서 원의 값이 바뀌었으면 했다.

원리를 쉽게 말하자면 아래 사진을 보면 된다.

내 마우스의 위치가 A에 있을때 B에 해당하는 위치에 슬라이더 값이 있어야 한다는 뜻이다.

 

슬라이더 핸들이 드래그 중인 마우스의 위치와 직선상에 있어야 한다는게 포인트.

 

 

 

소스를 바로 봐 보자.

Canvas의 Render Mode가 Camera인 경우

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class CircularSlider : MonoBehaviour, IDragHandler, IPointerDownHandler
{
    public RectTransform handle; // 핸들 오브젝트
    public RectTransform centerPoint; // 중심점 오브젝트(따로 깡통 오브젝트 만들기)
    public Canvas canvas; // 현재 사용 중인 캔버스
    public Text valueText; // 값을 표시할 텍스트
    public Image fillImage; // 모드가 Radial 360 fill인 이미지

    public int maxChips = 280; // 최대 값 (100%에 해당)
    private float radius; // 중심점과 핸들 사이의 고정된 거리 (반지름)
    private float maxAngle = 260f; // 최대 각도 (260도)
    private float currentAngle = 0f; // 현재 핸들의 각도

    void Start()
    {
        // 중심점과 핸들 사이의 초기 거리(반지름)를 계산
        radius = Vector2.Distance(handle.anchoredPosition, centerPoint.anchoredPosition);
        UpdateHandlePosition(maxAngle); // 초기 위치를 0%로 설정
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        UpdateHandlePosition(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        UpdateHandlePosition(eventData);
    }

    private void UpdateHandlePosition(PointerEventData eventData)
    {
        // 마우스의 화면 좌표를 캔버스의 로컬 좌표로 변환
        Vector2 localMousePosition;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(centerPoint, eventData.position, canvas.worldCamera, out localMousePosition);

        // 중심점에서 마우스 위치 사이의 벡터를 계산
        Vector2 direction = (localMousePosition - (Vector2)centerPoint.anchoredPosition).normalized;

        // 마우스 위치로부터 각도 계산 (0~360도)
        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        if (angle < 0) angle += 360; // 각도를 0~360도로 조정

        // 시계방향으로 돌 때 각도 제한
        if (angle > maxAngle)
        {
            currentAngle = maxAngle; // 시계방향으로 최대값을 넘어가면 멈춤
        }
        else
        {
            currentAngle = Mathf.Clamp(angle, 0, maxAngle);
            // 핸들의 새로운 위치 계산: 중심점에서 방향 벡터에 반지름을 곱한 거리만큼 이동
            Vector2 newPosition = (Vector2)centerPoint.anchoredPosition + new Vector2(Mathf.Cos(currentAngle * Mathf.Deg2Rad), Mathf.Sin(currentAngle * Mathf.Deg2Rad)) * radius;

            // 핸들의 위치를 업데이트
            handle.anchoredPosition = newPosition;

            // 현재 값 및 이미지 업데이트
            UpdateValueText();
            UpdateFillImage();
        }

    }

    private void UpdateHandlePosition(float angle)
    {
        // 초기 위치 설정 함수
        currentAngle = angle;
        Vector2 newPosition = (Vector2)centerPoint.anchoredPosition + new Vector2(Mathf.Cos(currentAngle * Mathf.Deg2Rad), Mathf.Sin(currentAngle * Mathf.Deg2Rad)) * radius;
        handle.anchoredPosition = newPosition;
        UpdateValueText();
        UpdateFillImage();
    }

    private void UpdateValueText()
    {
        // 각도를 최대 칩 수로 변환하여 텍스트 업데이트
        // currentAngle이 최대일 때 0이 표시되도록 반대로 계산
int currentValue = Mathf.RoundToInt((1 - (currentAngle / maxAngle)) * maxChips);

        valueText.text = currentValue.ToString();
    }

    private void UpdateFillImage()
    {
        // 각도를 0에서 1 사이의 값으로 변환하여 Radial Fill에 적용
        // FillAmount는 핸들이 움직인 비율로 설정해야 합니다.
        fillImage.fillAmount = currentAngle / 360;
    }
}

 

 

 

주석을 친절히 써놨으니, 대강 알것이다...

 

 

 

결과물:

근데 지금 보니 내가 색상을 반대로 해놨네;; 숫자가 올라갈때 색상이 채워져야 하는데ㅇㅅㅇ ㅋㄷㅋㄷ

뭐 아무튼..

 

UI는 정말 딱 참고만 하시고...

내가 한 방법은.

두 개의 원 이미지를 만들고 레이어상 뒤에 원을 크게 만들어서 지금처럼 초록색을 넣고 모드를 radial 360 fill로 넣었다. 

핸들은 0이어야 하는 지점에 미리 가져다 놓았다.

728x90

 

Assets/Plugins/Android/gradleTemplate.properties

에다가

android.enableR8 = true

를 넣어준다.

 

만약 gradleTemplate.properties파일이 없다면.

 

project setting > Player > Publishing Settings > Build > Custom Gradle Properties Template에 체크한다.

그럼 로딩되다가 파일이 생긴다.

 

 

여기 빨간 상자에 체크

 

 

 

아래는 내 gradleTemplate.properties파일 코드.

org.gradle.jvmargs=-Xmx4096m
org.gradle.parallel=true

unityStreamingAssets=your_streaming_assets_path_here
# Android Resolver Properties Start
android.useAndroidX=true
android.enableJetifier=true
# Android Resolver Properties End

additional_properties_here
android.enableR8=true

 

 

 

 

 

 

 

 

728x90

 

 

빌드시 이런 에러가 나오면 중복된 Class가 있다는 것이다.

 

 

 

해결방법:

 

1. 프로젝트 영역에서 " 2"를 검색해보자. 그냥 2가 아니고 "띄어쓰기2"

 

2. 그럼 파일이름 끝에 " 2"가 있는게 있을 것이다.

예) AndroidManifest 2.xml
이런식으로.

 

3. 그걸 지운다. 

 

4. 그럼 다시 빌드를 하여, 또 다른 빌드에러를 맛보러 간다.

 

728x90

 

 

문제 : 자식 아래에 클릭이벤트가 있는 부모가 있는 상태에서 자식을 눌렀을 경우에 부모가 클릭된다.

회색이 부모고, 흰박스가 자식이라 했을때.

 

목표 : Raycast Target 기능을 사용하지 않고, 자식을 눌렀을 때 반응이 없어야 한다

해결 : Raycast Target의 값을 수정하지 않아야 하는 경우. 꼼수지만... 흰박스에 버튼 공갈 컴포넌트를 넣으면된다. Transition은 None으로 주고.

걍 이렇게.

 

 

나야 뭐 정석적으로 하는 사람도 아니고... 나느 이런 경우는 많지 않아서 그냥 이렇게 쓴다.!

728x90

 

 

문제: 유니티 에디터에서 드래그로 크기 조정을 하면서 Alt를 누르게 되면 Rect Transform의 값이 NaN가 되는 경우가 있다.

해결: Pivot의 X 또는 Y 값이 0또는 1로 되어 있는게 있는지 확인해봐야 한다.

 

이유:

Alt를 누르고 크기 조정을 하겠다는 뜻은 양쪽으로 같이 크기를 조정하겠다는 것이다.

근데 0 또는 1로 하게 되면 유니티 내의 계산이 이상해진다.

 

예를 들어서.

Pivot Y를 0.9로 하고 Alt와 함께 크기 조정을 해보면, 이상한 비율로 양쪽으로 늘어날 것이다.

비율로 생각했을때 10%는 위로, 90%는 아래로 양쪽으로 늘어나기 때문이다.

 

그러니까... 만약 0 또는 1로 하게 되면 이상한 계산식이 되어 버리는거다.

위쪽은 0%만큼 위로 늘어나고 아래로는 100%만큼 아래로 늘어나야 하는데, 이게 그냥 생각해도 이상하다.

 

 

전부터 가끔 이 에러가 나왔을 때는 무시했는데, 짱나게 굴어서 원인이 뭔지 좀 찾아봤다...

끄읏~

 

728x90

문제점: public bool testBool = false; 이렇게 초기화를 했는데도 계속 초기화 값이 반대값 일때...
해결: 유니티 에디터를 보시라. 

스크립트에는 false 로 줬지만, 에디터에는 체크가 되어 있어서 계속 true가 됐다.. .샹...

728x90

 

문제점: 한 글자씩 타이핑 줄때 <color~ 같은 태그가 유저에게 보인다. </color> 까지 닫아줘야 색상이 지정된다.
해결: 임시 제어문자를 넣어준다. 

 


    string testStr = "안녕하세요. r거두절meb입니다.";

    public IEnumerator ShowText(string fullText, Text txtCompo)
    {
        string displayText = ""; // 표시할 최종 문자열
        string color = "black"; // 기본 색상

        for (int i = 0; i < fullText.Length; i++)
        {
            if(fullText[i] == 'r'){
                color = "red"; // 빨간색 설정
                continue;
            } else if(fullText[i] == 'b'){
                color = "black"; // 검정색 설정
                continue;
            }

            // 현재 문자에 적절한 색상 적용
            displayText += $"<color={color}>{fullText[i]}</color>";

            txtCompo.text = displayText;
            yield return new WaitForSeconds(0.1f);
        }

        juniorScriptCoroutine = null;
    }

 

사용법: r, b는 내가 넣은 임시 문자고 필요에 따라 다른걸 넣어주면 된다.
r뒤부터는 빨간색이 나오고, b뒤부터는 검정색이 나올 수 있도록했다. 
r, b 차례일때는 다음 폰트의 color만 바꿔주는 역할만 하고 텍스트에 들어가지 않도록 continue를 해준다.

 

 

728x90

내게 필요했던 점: 데이터를 저장할 곳, DATA CRUD + 개발 중 손쉽게 수정이 가능하게.
해결 방법: Json텍스트저장, scriptableObject, simpleSQL 등. 그 중 데이터를 쉽게 넣고 한 눈에 보기 쉬운 SimpleSQL을 선택했다.

< 준비물 >
1. 에셋스토어에서 구매를 하고 다운을 받아서 임포트를 한다.(Demo도 함께 인스톨)
2. DB Browser for SQL을 다운 받는다. https://sqlitebrowser.org/dl/

준비물만 있으면 끝이다.
SimpleSQL > Demos > DataBases를 보면 데이터베이스가 있는 걸 볼 수 있다.
CRUD는 데모에 있으니 쿼리를 잘 확인해 보면 될것이고... 내가 원하는건 대량으로 데이터를 넣는 것이다.
그렇기 때문에 코드로 하는게 아니고 db툴로 하고 싶었다.
초기데이터는 SimpleSQL > Demos > DataBases 여기에 있는 데이터가 초기 데이터라고 보면 된다. 게임을 최초로 시작하면 제공될 데이터.

아래 이미지를 보면 DbManager의 Simple Sql Manager스크립트에 Change Working Name이 SciFi.sqlite라고 되어 있다. 내가 테이블 데이터를 변경할때 저 이름의 db를 변경하겠다는 뜻이다.


이제 db툴을 이용하기 위해 저 SciFi.sqlite라는 db파일이 실제로 어디에 있는지 알아야 한다.

string dataPath = Application.persistentDataPath;  
Debug.Log("Persistent Data Path: " + dataPath);

위 로그를 찍어보면 영구적으로 데이터를 저장할 수 있는 경로가 나온다. 게임을 지워야 사라지는 데이터다.
가보면

이렇게 있다.

이 파일을 아까 다운 받았던, DB Browser for SQLite에 끌어다 넣는다.

그럼 위 처럼 나온다. 이미지 상단 탭의 데이터베이스 구조, 데이터 보기 등을 보면서 툴 구조를 살펴보고, 데이터를 만져보쟈!

+ Recent posts