Post

Unity 1차 미니 프로젝트 - 마무리

해당 내용의 전부는 학원에서 배우는 것이기 때문에 공개가 어렵습니다.

해당 내용의 자세한 강의가 필요하신 분들은 이곳에서 확인하시면 됩니다.

2023-11-03 TIL

프로젝트의 마무리와 시연영상 그리고 깃과 협업에 관하여…

알고리즘 문제

오늘의 알고리즘 문제 : 약수의 합

정수 n을 입력받아 n의 약수를 모두 더한 값을 리턴하는 함수, solution을 완성해주세요.

1
2
3
4
5
6
7
public class Solution {
    public int solution(int n) {
        int answer = 0;
        return answer;
    }
}

Desktop View

해결

이문제의 접근법은 모든 수의 약수는 자기 자신을 제외하면 자신의 절반을 못넘는것에 있었습니다.

그래서 리턴값 변수인 answer에 제일 큰 약수인 자기 자신을 주고 for문의 조건식을 사용하여 int i는 1부터 n+1 / 2값 즉 int n의 반값까지 반복을 돌게 했습니다.

그리고 그 값을 i로 나머지 연산을 해 나머지가 없는 i값을 answer에 더해줍니다.

그렇게 되면 answern의값을 이미 가지고 있고 거기에 n을 제외한 n의 약수들의 합이 완성됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Solution {
    public int solution(int n) {
        int answer = n;
        for(int i=1; i< n+1/2; i++)
        {
            if(n%i ==0)
            {
                answer += i;
            }
        }
        return answer;
    }
}

Desktop View

프로젝트 시연영상

  • 구현한 기능들 (공통사항)

    1. 사운드 구현 (gif라 사운드가 안나오는 점 양해부탁드립니다)

Desktop View

  • 구현한 기능들 (타이틀 화면)

    1. 타이틀 화면 구현 및 캐릭터 클릭시 캐릭터 점프 애니메이션

    2. start버튼 클릭시 난이도 선택화면 구현

    3. 타이틀

Easy

Desktop View

영상이 너무 길어 중간은 잘랐습니다.

Hard

Desktop View

  • 구현한 기능들 (메인게임)

    1. 첫 시작시 튜토리얼 UI 표시 및 시작시 카드 등장 애니메시연 구현

    2. 카드 오픈시 애니메이션 구현

    3. 하단에 조커 카드 표시 및 조커카드 선택시 3초 감소 및 감소 애니메이션

    4. 카드 페어 시 이름 출력 애니메이션 및 점수 부여, 단 조커 페어 선택시 게임 오버

    5. 트라이 횟수 표시

    6. 트라이 횟수 및 남은 시간을 계산한 점수 구현 및 최고점수 저장 기능 구현

    7. 게임 오버 또는 승리시 판넬 등장 구현 및 ReTry, Title 버튼 구현

    8. 시간이 얼마 안남을 시 타이머 애니메이션 변경 기능 추가.

    9. 한번 뒤집은 카드 색상 변경 기능 추가

    10. 게임 우측 상단에 타이틀로 돌아갈수 있는 버튼 구현

Desktop View

내가 구현한 기능들

  1. 카드마다 이미지 넣기

  2. 카드 매칭 및 조커 카드 판별 기능 제작

  3. 카드 오픈 기능 및 카드 등장과 오픈 애니메이션 제작

  4. 조커 선택시 -3초 감소 기능 및 애니메이션 제작

구현 및 협업시 어려웠던 점과 해결법

  1. 난이도에 따른이미지를 넣을 때 모든 사진에 랜덤성을 부여하면 페어가 안나오는 경우가 생겼습니다. 또한 랜덤 조커가 너무 많은 양이 들어갈 경우가 있습니다.

    • 구현시 난이도에 따른 카드의 갯수를 통하여 배열 규칙을 만들어 활용해 이미지 넣기를 구현하였습니다. 코드의 일부분입니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    
     //난이도 설정
      switch (GameManager.Instance.Difficulty)
     {
         case DIFFICULTY.EASY:
             widthNumber = heightNumber = 4;
             GameManager.Instance.GameTime = 40f;
             GameManager.Instance.difficultyBasicScore = 60;
             GameManager.Instance.cardScore = 10;
             break;
         case DIFFICULTY.NORMAL:
             widthNumber = 4;
             heightNumber = 5;
             cardCenterValue = new Vector2(-1.58f, -3f);
             GameManager.Instance.GameTime = 50f;
             GameManager.Instance.difficultyBasicScore = 80;
             GameManager.Instance.cardScore = 15;
             break;
         case DIFFICULTY.HARD:
             // cardScale 줄여야함
             widthNumber = 5;
             heightNumber = 6;
             cardCenterValue = new Vector2(-1.78f, -3.2f);
             cardScale = 0.85f;
             GameManager.Instance.GameTime = 90f;
             GameManager.Instance.difficultyBasicScore = 120;
             GameManager.Instance.cardScore = 18;
             break;
     }
    
     //난이도를 이용한 배열 길이와 그에 따른 카드 이미지 넣기
    
     int[] CardImages = new int[widthNumber * heightNumber];
    
     for (int i = 0; i < widthNumber * heightNumber; ++i)
         CardImages[i] = i / 2;
    
     //순서의 랜덤성 부여
     CardImages = CardImages.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();
    
     //for문을 통한 카드 생성
     for (int i = 0; i < widthNumber * heightNumber; ++i)
     {
         GameObject card = Instantiate(cardPrefab);
         card.transform.parent = parents;
    
         float x = (i % widthNumber) * cardBlank;
         float y = (i / widthNumber) * cardBlank;
    
         card.transform.position = new Vector3(x, y, 0);
    
         string cardName ="CardImage" + CardImages[i].ToString("D2");
    
         card.transform.name = cardName;
         card.transform.Find("Front").GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>(cardName);
     }
    

    이런식으로 카드에 랜덤성과 배열의 규칙화를 사용하였습니다. 각자의 사진은 0~4번에 한장씩, 5~9번에 한장씩 식으로 나머지연산을 하였을 때 쉽게 구할수 있도록 하였습니다.

    Desktop View

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    // 카드 판별과 마찬가지로 나머지 값이 4일 때만 게임 종료
    if (int.Parse(secondCardImage.Substring(secondCardImage.Length - 1)) % 5 == 4 &&
        int.Parse(firstCardImage.Substring(firstCardImage.Length - 1)) % 5 == 4)
    {
        GameOver();
    }
    else // 아닐 경우 점수 추가
    {
        Instance.CurrentScore += cardScore;
    }
    

    조커는 나머지 연산시 4가 나올 때가 조커나 나옵니다. 그렇게 되므로 난이도별 조커는 1페어씩 나오게 됩니다.

    Desktop View

  2. 등장애니메이션 구현시 카드 몰림 현상

    • 전 포스팅에서 다루었던 내용입니다. 간략하게 설명하자면 애니메이션을 만들어 적용했을 때 카드가 한쪽으로 몰리는 현상이 발생하였습니다.

      그래서 알아본 결과 애니메이션을 적용할시 프리팹 자체의 포시션값을 변경할시 발생하는 현상이였습니다.

      그래서 해당 프리팹의 자식오브젝트에 애니메이션을 적용시 잘 작동되는 모습을 볼수 있었습니다.

    Desktop View

  3. 협업시 충돌 및 코드 가독성

    • 코드 및 씬 충돌이 생각외로 많이 일어났습니다. 하지만 같이 작업을 하며 코드구간이 겹치는 일이나 수정이 많았고 충돌을 해결해야하는 경우가 많이 생겼습니다. 하지만 같이 협업을 하는 입장으로 혼자서 충돌을 해결하기보다는 다른 팀원들과 이야기하며 필요한 부분과 필요없는 부분을 같이 도려가며 최대한 게임의 코드의 가독성을 향상시키켰습니다.

      또한 코드를 아무리 가독성있게 만든다고 해도 다른 사람이 만든 코드를 보고 바로 무슨 기능을 하는지 잘 알수가 없습니다.

      그로 인해 각자 작업한 부분에 주석을 최대한 간결하며 알기 쉽게 달아주는 것이 정말 중요하다고 생각하였습니다.

    Desktop View

오늘의 정리

유니티로는 처음 협업을 해보는 시간이었다.
다른 개발과 달리 유니티는 생각보다 충돌이 일어나는 경우가 많았다.
하지만 그로인해 다음부터는 이 충돌들을 어떻게 하면 안낼수 있을까에 대한 생각을 많이 했다.
그렇게 생각해본 결과 해야하는 해결 과정을 단순하게 생각하는게 아니라 여러가지 경우의 수를 생각해야한다는 것이였다.
하나의 오류나 버그가 생겼다면 그것을 해결하는 방법을 여러방면으로 생각해보아야한다는 것이다.
하나의 방법으로만 계속 버그나 오류를 고치다가 해당 방법으로 해결이 안되는 경우가 생길수도 있는것이다.
그때 여러방법으로 해결을 해봤다면 시도해봤던 여러가지 방법을 사용해 해결할수 있을수 있을것이다.
또한 그러면서 여러 기능을 익히며 습관을 잘 들이면 나중에 유니티 뿐만 아니라 여러가지 다른 툴을 사용할 때도 조금더 수월할게 익숙해지면 좀더 잘 사용할수 있을것이다.

Desktop View

This post is licensed under CC BY 4.0 by the author.