Unity 본캠프 5일차 - 미니 프로젝트

한예준·2025년 4월 11일

오늘은 팀에서 진행했던 프로젝트의 발표날이다. 우리는 GitHub의 Readme파일에 발표 내용을 정리했다. 주요 정리점은 다음과 같다.


우리팀의 프로젝트

프로젝트 명

  • 맴버 카드 프로젝트

프로젝트 소개

  • 우리 팀, 우리만의 이야기를 담을 수 있는 ‘팀원 소개 카드게임’ 으로 만드는 것을 목표로 한다.

팀원 소개

필수기능 제작

  • 과제목표
    한 사람 당 본인을 대표할 수 있는 이미지를 필요한 만큼 준비해주세요.
    모든 카드 매칭 성공 시, 팀원들의 이름 및 사진 한 눈에 보여주기 / 실패 시 실패를 알리는 문구 노출
    추가 기능 구현을 살펴보고 게임에 여러 요소를 더하여 우리만의 게임을 제작해봅시다.
  • 시연 영상 첨부

추가기능 제작

  • 추가기능 기획
    • 난이도 시스템 구현
      히든 스테이지: 20장 (5x4), 중간에 화면 가리는 오브젝트 출현
      게임진행을 0->30초에서 60->0으로 변경
    • 스테이지 클리어 시 아바타 및 사진 UI표시
      기존 클리어 UI → 히든 스테이지 클리어 UI로 변경
    • 게임 연출 추가
      각종 행동에 사운드 삽입
  • 시연 영상 첨부

트러블 슈팅

  • GitHub merge 과정에서의 오류
  • Button 컴포넌트 오류
  • Card 애니메이션 관련 오류
    등이 있었고, 이를 해결하는 과정을 담았다.

이렇게 정리한 내용을 토대로 발표 준비를 진행하였으며, 곧 타팀들의 발표도 시작되었다.


타 팀들의 프로젝트

  • 먼저 다른 팀들은 게임들의 씬 디자인이 수려했다. 우리는 기능 구현에 집중해서 신경쓰지 못한 부분이었는데, 확실히 디자인이 수려한 게임에 더 손이 갈 수밖에 없는 것 같다.
  • 추가 기능들도 다양했다. 어떤 팀은 애니메이션에 신경을 쓰는 경우도 있었고, 어떤 팀은 게임 내에서 플레이어에게 커스텀할 수 있도록 하는 등 다양한 기능들을 추가한 것을 확인할 수 있었다.
  • 또 다양한 문제상황이 발생했는데, 이러한 문제상황을 해결할 때의 접근법을 배울 수 있었다.

느낀 점

  • 하고 싶어지는 게임을 만들기
    • 아무리 기능이 좋고 재미가 있는 게임이라도 디자인때문에 손이 안 가면 쓸모없다. 확실히 디자인에 신경을 써야 손이 갈 것 같다. 앞으로의 프로젝트에서는 최대한 디자인 감각을 살려보겠다.
  • 기능을 구현하는 법은 다양하다.
    • 같은 기능이더라도 다양한 방식으로 구현할 수 있다는 걸 알았다. 마치 같은 내용을 전달하더라도 다른 표현으로 전달할 수 있듯이 말이다. 다양한 구현법들을 익혀서 적절하게 사용하는 법을 배워나가겠다.
  • 문제상황은 누구에게나 발생한다.
    • 다른 팀들도 다양한 문제 상황들이 발생했다. 문제 상황은 언제든 누구에게나 발생할 수 있으니 문제 상황을 맞닥뜨렸을 때 해결하는 방법을 정확히 알아야겠다.
  • 팀원과 소통 적극적으로 하기
    • 프로젝트를 진행하면서 많은 문제상황을 겪었지만, 적극적인 소통이 따라온다면 해결할 수 있을 것이라는 믿음이 생겼다. 조금 더 적극적인 의사소통과 관계 형성을 통해 원활한 협업을 진행하도록 하겠다.

TIL

다음으로 지금까지 이 velog에 작성했던 TIL Post를 어떻게 더 효과적으로 작성할 수 있을지에 대해 수강하였다.

TIL을 쓰는 목적

  • 기록을 위해서
    • 프로젝트가 끝난 뒤, 나의 프로젝트를 어필하기 위한 기술 포트폴리오
    • 프로젝트 진행 중 사용한 기술을 리마인드하기 위해 TIL 참고.
  • 복습을 위해서
    • 프로젝트가 끝나고 점검할 때 다시 보고 이해하지 못하는 경우 발생
    • 나만의 언어로 표현하며 체득하는 과정 필요.
  • 증명을 위해서
    • TIL에 명시한 기술을 쓸 수 있다는 증명
    • 남들보다 더 열심히 할 수 있다는 증명
    • 신입이 가장 빠르게 경험, 실력, 성실함을 증명하는 방법 \rarr TIL

    TIL 작성 요령

  • 공부 시간을 포기하면서까지 작성하지 말 것.
  • 내가 고민한 내용이 기술적으로 맞는지 점검할 것.
  • 공부한 내용을 정리할 것.
  • 하루에 대한 회고를 작성할 것.
  • 문제점/시도해본 것/해결 방법/알게 된 것 순서로 작성할 것.

랜덤 타워 디펜스 모작

오늘 남은 시간은 랜덤 타워 디펜스에서 핵심 기능 중 하나인 타워 업그레이드 기능을 만들도록 하겠다. 랜덤 타워 디펜스의 타워 업그레이드 시스템은 다음과 같다.

  • 타워 업그레이드 시스템

    • 같은 종류이면서 같은 등급의 타워 2개를 조합하면 다음 등급의 랜덤 타워로 업그레이드
    • 타워 등급은 최대 5등급까지 지원
    • 타워의 능력치는 높은 등급일수록 상승타워의 능력치(공격 범위, 공격력, 공격 속도 등)는 높은 등급일수록 상승

    이 시스템을 충족시킬 수 있도록 구현 순서를 구상해보겠다.

  1. 타워 정보 구조 정리, 프리팹 구성
  • 각 타워가 GradeNumber 정보를 갖도록 만든다.
  • Inspector에서 설정 가능하게 만들었다.
  • Tower.cs
public class Tower : MonoBehaviour
{
    [Header("타워 정보")]
    public string towerGrade;        // 예: "Normal", "Rare", "Unique", ...
    public int towerTypeNumber;      // 예: 1 ~ 8
}
  • 예시) Tower_Normal_1.prefab
    towerGrade: "Normal"
    towerTypeNumber: 1
    이후 Tower_Normal_1.prefab 부터 Tower_Legendary_8.prefab까지 생성했다.
  1. 업그레이드 함수 TryUpgrade() 정의
  • 선택된 타워와 등급과 넘버가 같은 타워를 씬 전체에서 찾는다.
  • 타워를 찾으면 다음 등급의 랜덤 타워를 생성하고 기존 타워 2개를 제거한다.
 void TryUpgrade()
 {//타워 탐색
    Tower[] allTowers = FindObjectsOfType<Tower>();

    foreach (Tower other in allTowers)
      {
        if (other != this &&
            other.towerGrade == this.towerGrade &&
            other.towerTypeNumber == this.towerTypeNumber)
          {
            Vector3 spawnPos = transform.position;

            // 다음 등급의 타워 생성
            TowerSpawner.Instance.SpawnUpgradedTower(towerGrade, towerTypeNumber, spawnPos);

            // 선택된 타워와 대상 타워 제거
            Destroy(other.gameObject);
            Destroy(this.gameObject);

            return;
          }
        }
  }
  • 타워가 제거된 타일에 타워가 다시 생성되지 않는 오류가 발생했다.
  • 제거된 타워의 타일은 tile.isOccupiedfalse로 바꿔준다.
 private void OnDestroy()
 {
    RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.zero);
    if (hit.collider != null)
        {
        Tile tile = hit.collider.GetComponent<Tile>();
        if (tile != null)
           {
            tile.isOccupied = false;
           }
         }
   }
  • 타워가 제거된 자리에 tile이 있는지를 물리적으로 확인하여 만약 tile이 존재하면 그 tile 오브젝트를 가져오고, 그 tileisOccupied값을 false로 돌린다.
    • E키와 함께 마우스 클릭을 하면 TryUpgrade()함수를 불러온다.
private void OnMouseDown()
{
    if (Input.GetKey(KeyCode.E))
        {
        TryUpgrade();
        }
 }
  1. TowerSpawner에 업그레이드 생성 함수 만들기
  • 현재 타워 등급을 기준으로 다음 등급의 랜덤한 타워를 생성
  • 먼저 타워 프리팹을 가져올 배열을 생성한다.
  • SpawnUpgradedTower()
public void SpawnUpgradedTower(string currentGrade, int currentType, Vector3 position)
    {
    string nextGrade = GetNextGrade(currentGrade);             // 다음 등급 이름 반환
    GameObject[] pool = GetTowerPool(nextGrade);               // 해당 등급 프리팹 배열 가져옴

    if (pool == null || pool.Length == 0)
        {
        Debug.LogWarning($"[Upgrade 실패] {nextGrade} 등급 타워 프리팹이 없음");
        return;
        }

    int rand = Random.Range(0, pool.Length);                   // 0~7 중 랜덤
    GameObject newTower = pool[rand];
    Instantiate(newTower, position, Quaternion.identity);      // 선택한 타워 위치에 다음 등급의 랜덤 타워 생성
    }
  • GetNextGrade(): 현재 등급에서 다음 등급으로 넘어감
  • GetTowerPool(): 다음 등급에 해당하는 배열을 가져옴
 private string GetNextGrade(string grade)
 {
    switch (grade)
     {
        case "Normal": return "Rare";
        case "Rare": return "Unique";
        case "Unique": return "Epic";
        case "Epic": return "Legendary";
        default: return null;
      }
 }

 private GameObject[] GetTowerPool(string grade)
 {
    switch (grade)
     {
        case "Normal": return normalTowers;
        case "Rare": return rareTowers;
        case "Unique": return uniqueTowers;
        case "Epic": return epicTowers;
        case "Legendary": return legendaryTowers;
        default: return null;
     }
  }
  • 업그레이드 할 때 가져올 등급과 프리팹을 지정한다.
  • 이후 TowerSpawner 오브젝트에 각 타워들을 연결시킨다.
  1. 타워의 능력치들을 임의로 설정해주었다.
  • Tower_Normal의 스케일을 0.3으로 조절하고 등급이 올라갈 때마다 0.1씩 키웠다.
  • Tower_Normal의 사정거리가 3이고, 공격속도가 1이므로, 등급이 올라갈 때마다 사정거리를 1씩 늘리고, 공격속도는 두배씩 빠르게 만들었다.

이후 게임을 실행해보았다.

의도한 대로 실행되고 있음을 확인했다.


추후 개발 계획

다음 시간에는 무엇을 더 추가할 지 구상해보고 오늘 TIL을 마치고자 한다.

게임 플레이 확장

  • 웨이브가 진행될수록 적 체력 증가
  • 10라운드마다 보스 등장
  • 플레이어 체력 적용 및 게임 패배 조건 추가
  • 퀘스트 생성(예시: 서로 다른 Normal_Tower 8기를 전부 모으면 200원 추가 등)
  • 타워 개체별 차별화 (공격력, 투사체 사거리, 범위 공격, 디버프 적용 등)

UI & 연출 추가

  • 투사체 이펙트

  • 적 사망 이펙트

  • UI: 체력바, 골드 표시, 다음 웨이브까지 남은 시간 등

  • 게임 클리어/ 오버 화면

    (가능하다면) 타워 프리팹 구조 리팩토링

  • 현재 카드 프리팹을 하나하나 지정하고 있는데, 이를 코드로 리팩토링하여 타워 정보를 분리.


회고

  • 한 주를 마무리 하며, 이번 주에 팀 프로젝트를 진행하면서 정말 많은 걸 배웠다.
    • Git Hub 사용법을 배웠다.
    • 팀원들과의 의사 소통의 중요성을 다시금 깨달았다.
    • 다른 팀들과의 비교 분석을 통해 같은 기능이라도 다른 스크립트를 적용하는 등, 코드의 다양성과 확장성을 확인했다.
    • 문제 상황에 대해 대처하는 방법을 배웠다.

앞으로 있을 다양한 프로젝트의 방향성을 어림잡아 볼 수 있는 한 주 였다고 생각한다.
다음주의 발제 내용은 C# 문법이다. 지금까지 Unity 실습하면서 C#을 계속 접했는데, 그만큼 C# 문법을 익히는 것이 중요함을 알고, 다음주 학습에 더욱 집중하도록 하겠다.

0개의 댓글