TIL(Today I Learned)

[Unity] 리듬게임 채보 툴 제작(2) - TIL#47

Najdorf 2024. 3. 5. 12:18
728x90

트러블 슈팅

 

1. Hierarchy 상 삼촌관계의 오브젝트의 컴포넌트를 가져오기

 

 

위의 Hierarchy 상 각각의 GridBtn 객체

가 속해있는 Bar 오브젝트 하위의 BarNum의 String 값을 가져오고 싶은 게 목적이었다. 처음에는 GridBtn 스크립트 에서 GetComponentInParent 를 사용해서 가져오려 했으나, 당연하게도 작동하지 않았다.

 

그래서 GridBtn에서 바로 BarNum으로 접근하려고 시도하지 말고, Bar 스크립트에서 GetComponentInChildren으로 BarNum의 정보를 가져온 다음 GridBtn에서 그것을 참조하는 식으로 해결했다.

GridBtnBehaviour.cs

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class GridBtnBehaviour : MonoBehaviour, IPointerDownHandler
{
    private BarBehaviour _currentBarScript;
    private Vector3 _pos;

    private void Awake()
    {
        _currentBarScript = GetComponentInParent<BarBehaviour>();
        _pos = this.transform.localPosition;
    }

    void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 좌클릭 시 노트 생성
            PatternManager.Instance.CreateSingleNote(_currentBarScript.CurrentBarNum, _pos.x, _pos.y);
        }
    }
}

BarBehaviour.cs

using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class BarBehaviour : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    public int CurrentBarNum // 현재 Bar의 순번을 return 합니다.
    { 
        get { return int.Parse(_currentBarTxt.text.Replace("bar ", "")); }
    }

    private Image _barImage;
    private TextMeshProUGUI _currentBarTxt;
    private GameObject _beat4;
    private GameObject _beat8;
    private GameObject _beat12;
    private GameObject _beat16;

    private UnityEngine.Color redColor;
    private UnityEngine.Color defaultColor;
    private bool isPointerIn;
    private bool isPresetExists;

    private void Awake()
    {
        _barImage = GetComponentInChildren<Image>();
        _currentBarTxt = this.GetComponentInChildren<TextMeshProUGUI>();

        _beat4 = Resources.Load<GameObject>("Prefabs/Sequencer/InputPresets/Beat(4)");
        _beat8 = Resources.Load<GameObject>("Prefabs/Sequencer/InputPresets/Beat(8)");
        _beat12 = Resources.Load<GameObject>("Prefabs/Sequencer/InputPresets/Beat(12)");
        _beat16 = Resources.Load<GameObject>("Prefabs/Sequencer/InputPresets/Beat(16)");

        redColor = new Vector4(150f / 255f, 72f / 255f, 72f / 255f, 134f / 255f);
        defaultColor = new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 134f / 255f);
        isPointerIn = false;
        isPresetExists = false;
    }
		// 이하 생략
}

 

 

 

 

2. 노트를 찍은 위치와 노트가 생성되는 위치가 일치하지 않는 문제

 

 

개발하고 있는 패턴 시퀀서의 작동 방식은 다음과 같다.

 

위 순서도를 통해 강조하고 싶은 점은, Bar를 클릭하면 선택된 Bar 내부에 선택한 비트 수에 맞춰 미리 만들어진 GridBtn과 Line의 프리팹이 생성되고, 그렇게 만들어진 GridBtn 객체를 좌클릭을 하면 PatternManager의 CreateSingleNote 메서드가 작동한다는 점이다. 그리고 CreateSingleNote 메서드의 매개변수로는 순서도 상에는 나와있진 않지만 (int barNum, float xPos, float yPos) 이다.

 

이 때 매개변수로 넘겨주는 값은 각각 다음과 같다.

  • int barNum, 현재 선택된 GridBtn이 속한 Bar의 인덱스 번호
  • float xPos, 현재 선택된 GridBtn의 localPosition의 x좌표 값
  • float yPos, 현재 선택된 GridBtn의 localPosition의 y좌표 값

이 정보를 통해 전체 Grid 좌표계에서의 노트 좌표를 맞춰 생성해야 하는 게 목적이었지만, 생각대로 잘 풀리지 않고 어긋나는 현상이 빈번히 일어났다.

 

 

그래서 여러 번의 시도와 계산 끝에, 생성되는 각 노트의 좌표와 xml 파일에 저장할 tick 값을 계산한 결과는 다음과 같다.

public void CreateSingleNote(int barNum, float xPos, float yPos)
{
    // GridBtnBehaviour.cs 에서 호출

    int index = (int)((xPos + 240f) / 160f);
    int tick = (int)((yPos + 320f) * (1 / hpt) + (tpm * barNum));
    bool isNoteExists = _xml.tracks[index].Contains(tick);

    if (!isNoteExists)
    {
        float yScale = _grid.transform.localScale.y;
        float yOffset = _grid.transform.position.y;
        float y = (yPos + 640f * barNum) * yScale + yOffset;

        switch (index)
        {
            case 0: // 1번 트랙
                Instantiate(_noteBlue, new Vector3(xPos, y, 0f), Quaternion.identity, _notes.transform);
                break;
            case 1: // 2번 트랙
                Instantiate(_noteOrange, new Vector3(xPos, y, 0f), Quaternion.identity, _notes.transform);
                break;
            case 2: // 3번 트랙
                Instantiate(_noteOrange, new Vector3(xPos, y, 0f), Quaternion.identity, _notes.transform);
                break;
            case 3: // 4번 트랙
                Instantiate(_noteBlue, new Vector3(xPos, y, 0f), Quaternion.identity, _notes.transform);
                break;
        }

        _xml.tracks[index].Add(tick);
    }

}

 

메모

 

1. grid 조작, 끌어서 드래그 앤 드롭
2. 마우스 휠로 확대/축소
3. 입력 프리셋 가져오기
4. 노트 찍기
5. 저장
6. 비트 선택 기능
7. 파일 선택 기능
8. XML note 오름차순 정렬

9. 곡 길이(ms), BPM 입력으로 songinfos 설정하는 기능 추가하기
10. Off Grid??? 는 어떻게 하지?
11. 되돌리기 기능은 어케하지?
12. 노트 안 지워지는 버그
13. 채보 툴 가이드
14. Shift 누른 상태에서 스크롤 하면 가속
15. 롱노트??

 

728x90