프로그래밍/유니티

[유니티] 롤 골드그래프를 만들어보자(1) - 점 찍기

갓똥 2021. 8. 9. 00:59
728x90
반응형

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

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

위와 같은 결과물을 만드는게 목표입니다.

 

일단은 골드그래프라고 했지만 데이터를 무엇을 쓰느냐에 따라 데미지나 받은피해량, 힐량 등 어디든 활용가능하게 하는것도 목표

 

하이라키는 이렇게 만들어놨습니다.

현재까지 게임화면으로 보이는 모습은

이건.. 꾸미기 나름이므로 사실 어떻게 만들어도 상관없지만 일단은 이런식으로 만들어놨습니다.

이제 점과 선을 만들어놔야합니다.

일단 점과 선도 딱히 이쁘게 보이기 위한 리소스를 쓸 생각없이 디폴트리소스를 이용할거라

코드상에서 동적으로 생성해도 되지만 귀찮기 때문에 그냥 미리 프리팹으로 만들어 사용하겠습니다.

편한게 최고지 않겠습니까

관련해서

점과 점사이에서 우세정도가 달라지면 선의 색이 중간에 바뀌는데 이것도 코드로 짤 수 있지만

편하게 이미지마스크를 사용해서 처리했습니다..

하지만 그래프 내부 색상 채우는건 마스크로 처리가 되지 않아 코드로 짰는데

겸사겸사 이런방법도 있고 저런방법도 있구나 정도로 봐주시면 좋겠습니다.

 

점과 선을 만들어봤는데 이정도면 충분할 것 같습니다.

프리팹으로 만들어줍니다.

 

점 프리팹

 

선 프리팹

 

이제

GraphMaker라는 스크립트를 만든 후 GoldGraph오브젝트에 붙입니다.

아, 그래프 영역은 x 800, y 360으로 했는데 사실 자유입니다. 코드상에서 가로 세로값을 가져다 쓸거라..

 

코드작성 시작!

에 앞서 데이터가 없는데 데이터는 (시간), (아군,적군 전체골드)로 받는다고 생각하고 만들었습니다.

따라서 먼저 임시로 쓸 임시 데이터부터 작성해놨습니다.

public class GraphMaker : MonoBehaviour
{
    Dictionary<int, int[]> AllTeamTotalGold = new Dictionary<int, int[]> { };

    void Start()
    {
        var rand = new System.Random();
        int BlueTeamGold = 0, PurpleTeamGold = 0;
        for(int time=0; time < 100; time++)
        {
            BlueTeamGold = BlueTeamGold + rand.Next(0, 1000);
            PurpleTeamGold = PurpleTeamGold + rand.Next(0, 1000);
            AllTeamTotalGold.Add(time, new[] { BlueTeamGold, PurpleTeamGold });
        }
    }
}

이제 기능 구현을 해보자


기능을 구현하기전에 어디부터 구현을 해나가야할지, 필요한게 무엇이 있을지 생각을 해봤습니다.

그 결과

  1. 받은 데이터를 기준으로 골드의 격차를 저장할 컬렉션을 하나 만든다.
  2. 격차의 최대값(절대값)을 찾아 따로 저장한다. => 이 최대값을 기준으로 나머지 값들의 y축을 정하기 위함
  3. 가로로 얼마나 점을 찍을지 정해야한다.
  4. 점을 먼저 찍는다.
  5. 각 점을 연결한 선을 찍는다.
  6. 그려진 그래프의 내부를 채운다.

정도로 생각했습니다. 

이제 생각한 순서대로 구현을 해보자.

 


1. 받은 데이터를 기준으로 골드의 격차를 저장할 컬렉션을 하나 만든다.

private void DrawGoldGraph()
{
    var comparisonValue = new Dictionary<int, int>();
}

어... 이게 끝이다.


2. 격차의 최대값을 찾아 따로 저장한다.

private void DrawGoldGraph()
{
    var comparisonValue = new Dictionary<int, int>();

    foreach (var pair in AllTeamTotalGold)
        comparisonValue.Add(pair.Key, pair.Value[0] - pair.Value[1]);
        // 양팀의 골드 격차 저장 +면 Blue팀이 우세, -면 Purple팀이 우세

    int MaxValue = comparisonValue.Max(x => Mathf.Abs(x.Value));
    // +와 -가 공존하므로 절대값으로 최대값을 찾는다.
    // 이 최대값은 이따 점을 찍을 때 y값의 최대값이 되고
    // 나머지는 최대값을 기준으로 y값을 정해서 찍을 예정이다.
}

3. 가로로 얼마나 점을 찍을지 정해야한다. +

4. 점을 먼저 찍는다.

public int SAMPLE_RATE = 10;
// 점을 찍을 횟수이다. const로 할까하다 테스트를 위해 일단 public필드로 만듬
public Gameobject Dot;
// 위에서 만든 점 프리팹
public Transform DotGroup;
// 생성한 점을 자식으로 둘 부모 오브젝트이다.
// 점들을 모아놓는 것과 선과 점의 그려지는 순서를 바꾸기에 편하다.
public Color BlueTeamColor;   // 블루팀 색상
public Colro PurpleTeamColor; // 퍼플팀 색상

public RectTransform GraphArea;
// 그래프 길이가 해상도에 따라 달라지므로.. 받아올 애 추가

private float graph_Width;
private float graph_Height;
// 길이, 높이 저장할 변수 추가

void Start()
{
    // ---
    // AllTeamTotalGold Setting...
    // ---
    
    graph_Width = GraphArea.rect.width;
    graph_Height = GraphArea.rect.height;
    // GraphArea의 가로 세로값을 가져온다.
    
    DrawGoldGraph();
}

private void DrawGoldGraph()
{
    float startPosition = -graph_Width / 2;
    // 그래프 영역의 길이 / 2에 -를 붙이면 시작위치가 된다.
    
    float maxYPosition = graph_Height / 2;
    // 그래프 영역의 높이 / 2 => 점을 찍을 최대 높이

    // ---
    // 격차 컬렉션 생성 및 저장, 최대값 저장...(위에꺼)
    // ---

    for (int i = 0; i < SAMPLE_RATE; i++)
    {
        // 점 오브젝트 생성 및 부모 설정, 각 컴포넌트 가져오기
        GameObject dot = Instantiate(Dot, DotGroup, true);
        dot.transform.localScale = Vector3.one;

        RectTransform dotRT = dot.GetComponent<RectTransform>();
        Image dotImage = dot.GetComponent<Image>();

        int tick = SAMPLE_RATE - 1 == i ? AllTeamTotalGold.Count - 1 : AllTeamTotalGold.Count / (SAMPLE_RATE - 1) * i;
        // 총 경기시간 / 샘플링할 수로 간격을 정해 값을 가져오지만
        // 마지막 경기 끝났을 때의 격차를 알고싶어 경기 끝난 시간을 따로 가져옴

        float yPosOffset = comparisonValue[tick] / MaxValue;
        // tick시간대의 골드격차 / 골드격차최대값 = -1.0f ~ 1.0f

        dotImage.color = yPos >= 0f ? BlueTeamColor : PurpleTeamColor;
        // 위 결과에 따라 격차가 0이여도 점은 BlueTeam색상을 하게 된다.
        // 이것도 엄격하게 0일때는 중립색으로 하겠다면 바꾸면 된다.
        
        dotRT.anchoredPosition = new Vector2(startPosition + (graph_Width / (SAMPLE_RATE - 1) * i), maxYPosition * yPosOffset);
        // 가로는 startPosition부터 각 격차마다 늘어나며 일정간격으로 찍히게 하였고
        // 세로는 격차/격차최대값에 따라 점이 찍힐 최대 높이에서 비율에 맞게 찍히게 하였다.
    }
}

 

쓰다보니 길어져 1편, 2편으로 나누어 올려야 할 것 같습니다.

이게 코드블럭안에서 주석으로 설명하는게 편할지 따로 빼는게 편할지

꾸미거나 가독성에 대한 부분은 떨어져서 뭐가 좋을지 감이 안잡히네요.

 

어쨋거나 포스팅은 점찍는 부분까지만 하고 다음편에 이어서 올리겠습니다.

 

점 찍기 완료

728x90
반응형