프로그래밍/유니티

[유니티] 롤 골드그래프를 만들어보자(3) - 그래프 내부 채우기

갓똥 2021. 8. 12. 02:21
728x90
반응형

UI를 이용하여 롤 골드그래프를 만들어보자

코드만 필요하신분은 아래로 내리시면 있습니다.

 

이전에 선까지 찍었으니 이제 그래프 영역 내부를 색칙할 차례입니다.


6. 그려진 그래프의 내부를 채운다.

이번에도 시작에 앞서 만들어야 할게 있습니다.

그래프 내부를 채우는건 동적으로 메쉬를 생성해서 넣어줄 Material이 필요합니다.

 

1. Blue와 Purple을 두개 만듭니다. 

색상은 자유지만 (전 Alpha값을 좀 줄였습니다. 보기 이쁘더라구요)

2. Shader는 UI/Default로 적용합니다.

 

public Transform InnerFilledGroup;
// 생성한 객체를 자식으로 둘 부모
public Material BlueMat;
public Material PurpleMat;

private void DrawGoldGraph()
{
    var innerFilled = new List<Vector3>();
    // 점들의 위치를 저장할 리스트
    // UI위의 점들이지만 Vector3로 저장해야한다.

    // ---
    // 격차 최대값 등...
    // ---

    for (int i = 0; i < SAMPLE_RATE; i++)
    {
        // ---
        // 점 찍기
        // ---
        
        // ---
        // 선 찍기
        // ---
    }
    
    CreateFilledGraphShape(innterFilled.ToArray()); 
}

private void CreateFilledGraphShape(Vector3[] linePoints)
{
    List<Vector3> filledGraphPointList = new List<Vector3>();
    // 삼각형의 정점의 좌표를 저장할 리스트
    Vector3 tmp;
    float x;
    // 색상이 바뀔 때 점을 추가로 리스트에 저장할 지역변수

    for (int i = 0; i < linePoints.Length; ++i)
    {
        filledGraphPointList.Add(new Vector3(linePoints[i].x, 0, 0));
        filledGraphPointList.Add(new Vector3(linePoints[i].x, linePoints[i].y, 0));

        if (i + 1 < linePoints.Length) // 그래프의 색상이 바뀔 때 대응
        {
            if (linePoints[i].y < 0 && linePoints[i + 1].y >= 0) // 아래에서 위로
            {
                x = Mathf.Lerp(linePoints[i].x, linePoints[i + 1].x, Mathf.Abs(linePoints[i].y) / (Mathf.Abs(linePoints[i].y) + Mathf.Abs(linePoints[i + 1].y)));
                tmp = new Vector3(x, 0f, 0f);

                filledGraphPointList.Add(tmp);

                MakeRenderer(filledGraphPointList.ToArray(), filledGraphPointList.Count, PurpleMat);

                filledGraphPointList.Clear();
                filledGraphPointList.Add(tmp);
            }
            else if (linePoints[i].y > 0 && linePoints[i + 1].y <= 0) // 위에서 아래로
            {
                x = Mathf.Lerp(linePoints[i].x, linePoints[i + 1].x, Mathf.Abs(linePoints[i].y) / (Mathf.Abs(linePoints[i].y) + Mathf.Abs(linePoints[i + 1].y)));
                tmp = new Vector3(x, 0f, 0f);

                filledGraphPointList.Add(tmp);

                MakeRenderer(filledGraphPointList.ToArray(), filledGraphPointList.Count, BlueMat);

                filledGraphPointList.Clear();
                filledGraphPointList.Add(tmp);
            }
            // 그래프의 색상이 바뀌었다면 일단 거기까지 MakeRenderer함수를 통해 Mesh를 생성
            // Mesh생성 후 filledGraphPointList는 초기화
        }
    }

    // filledGraphPointList를 통해 Mesh생성
    if (filledGraphPointList[filledGraphPointList.Count - 1].y >= 0)
    {
        MakeRenderer(filledGraphPointList.ToArray(), filledGraphPointList.Count, BlueMat);
    }
    else
    {
        MakeRenderer(filledGraphPointList.ToArray(), filledGraphPointList.Count, PurpleMat);
    }
}

private void MakeRenderer(Vector3[] graphPoints, int count, Material innerFill)
{
    int trinangleCount = count - 2; // 삼각형 개수
    int[] triangles = new int[trinangleCount * 3]; // 정점 수

    int idx = 0;
    int ex = trinangleCount / 2;
    for (int i = 0; i < ex; i++)
    {
        triangles[idx++] = 2 * i;
        triangles[idx++] = 2 * i + 1;
        triangles[idx++] = 2 * i + 2;

        triangles[idx++] = 2 * i + 1;
        triangles[idx++] = 2 * i + 2;
        triangles[idx++] = 2 * i + 3;
    }

    if (count % 2 == 1)
    {
        triangles[idx++] = 2 * ex;
        triangles[idx++] = 2 * ex + 1;
        triangles[idx++] = 2 * ex + 2;
    }

    Mesh filledGraphMesh = new Mesh();
    filledGraphMesh.vertices = graphPoints;
    filledGraphMesh.triangles = triangles;

    GameObject filledGraph = new GameObject("Filled graph");
    CanvasRenderer renderer = filledGraph.AddComponent<CanvasRenderer>();
    renderer.SetMesh(filledGraphMesh);
    renderer.SetMaterial(innerFill, null);
    filledGraph.transform.SetParent(InnerFilledGroup);
    filledGraph.AddComponent<RectTransform>().anchoredPosition = Vector2.zero;
}

코드가 딱히 설명이 필요 없어보인다.

 


최종 결과물

 

+ Dot 프리팹에 Outline 컴포넌트 추가하는 것도 괜찮은듯

 

최종코드는 다음 포스팅에 올리겠습니다.

728x90
반응형