내일배움캠프 60

[Unity] 타워 배치와 경로 검증을 위한 타일 + A* 알고리즘 기반 시스템

이번 포스팅에서는 팀 프로젝트에서 사용된 타워 설치와 적 경로 검증을 위한 타일 시스템에 대해 정리해보려고 합니다.처음에는 왜 이렇게 복잡하게 구현했는지 이해가 잘 안됐는데, 팀원에게 설명을 듣고 나니까 ‘아 그래서 A* 알고리즘이 필요했구나!’ 하고 납득이 갔습니다.처음엔 그냥 “타일이 비었으면 타워를 설치하면 되지”라고만 생각했었는데, 이 시스템은 그보다 훨씬 똑똑하고 견고하게 설계되어 있었습니다.전체 구조맵 데이터는 JSON으로 되어 있고, 이를 불러와서 2차원 정수 배열로 변환합니다각 타일은 설치 가능 여부 / 통과 가능 여부를 저장하고 있습니다타워를 설치할 때는 터치 좌표를 타일 좌표로 변환한 뒤, 해당 영역이 설치 가능한지 판단합니다설치가 가능하더라도 적의 이동 경로를 막는지 실시간으로 검증합..

[Unity] 가챠 연출에 스킵 기능 추가하기 (기존 연출 시스템 개선)

지난 글([Unity] 가챠 연출 시스템 구현)에서는 오퍼레이터 등장 연출을 DOTween으로 구성하고, nextButton을 눌러 다음 연출로 넘어가는 방식까지 구현해보았습니다.참고: https://danpat77.tistory.com/69이번에는 해당 시스템에 스킵 버튼을 추가하여 연출을 즉시 종료하고 최종 결과 상태로 전환되는 기능을 구현해보았습니다.스킵 기능을 만들게 된 이유현재 진행 중인 게임의 데모 버전을 플레이한 유저들로부터 다음과 같은 피드백을 받았습니다:“연출이 너무 길다.”“중간에 스킵하고 바로 결과를 보고 싶다.”게임 시스템적으로는 연출을 통해 오퍼레이터 획득의 희열을 주는 것이 목적이었지만, 모든 유저가 동일한 속도로 감상하기를 원하는 것은 아니었습니다.따라서 유저가 직접 연출을 스..

[Unity] #if UNITY_EDITOR 전처리기로 에디터 전용 코드 작성하기

Unity 프로젝트를 개발하다 보면, 게임 빌드에는 포함되지 않고 에디터에서만 실행되길 원하는 코드가 필요할 때가 많다. 예를 들어 디버깅 로그 출력, Gizmo 시각화, 또는 특정 테스트 코드 등을 작성할 때가 해당된다. 이때 유용하게 사용할 수 있는 것이 바로 #if UNITY_EDITOR 전처리기이다.#if UNITY_EDITOR란?#if UNITY_EDITOR는 C#의 전처리기 지시문으로, Unity Editor 환경에서만 코드가 실행되도록 분기 처리할 수 있다. 이 조건으로 묶인 코드는 실제 빌드 파일에는 포함되지 않기 때문에, 런타임 성능에 영향을 주지 않으면서도 에디터에서만 필요한 기능을 삽입할 수 있다.기본 사용법#if UNITY_EDITOR // 이 코드는 에디터에서만 실행된다#en..

[Unity] 오픈 시스템 팝업 구현 (큐 + 해시셋 조합)

이번에는 게임에서 새로운 시스템이 열렸을 때 보여주는 '오픈 시스템 팝업' UI를 구현해보았습니다.하나의 팝업만 순차적으로 보여주고, 중복되지 않도록 막기 위해 Queue + HashSet 조합을 활용했습니다.구현 목표새로운 시스템이 열렸을 때 자동으로 팝업을 띄움한 번 본 팝업은 다시 뜨지 않음 (PlayerPrefs)여러 개의 팝업이 동시에 등록되면 큐로 차례차례 출력중복된 index가 큐에 중복 등록되지 않도록 차단1초 후 '확인 버튼'이 활성화되어 자연스러운 연출 유도핵심 구조데이터 클래스[System.Serializable]public class OpenSystemData{ public Sprite icon; public string Desc;}각 팝업에 필요한 이미지와 설명 텍스트만..

[Unity] 가챠 연출 시스템 구현

가챠 시스템을 구현하다 보면 “결과 화면에서 어떤 식으로 오퍼레이터(캐릭터)를 보여줄까?” 하는 고민을 하게 됩니다.단순히 텍스트나 이미지만 띄우기보다는, 연출을 통해 사용자에게 인상 깊은 경험을 주는 것이 중요하다고 생각했어요.그래서 오늘은 유니티에서 가챠 결과 연출 시스템을 만들어 보았습니다.클래스 이름은 GachaEffectHandler로, 오퍼레이터의 등장 대사, 이미지, 직업 정보 등을 애니메이션과 함께 출력하는 역할을 합니다.RequestGachaEffect() – 외부에서 연출 요청public void RequestGachaEffect(OperatorTable operInfo){ if (!gameObject.activeSelf) gameObject.SetActive(true..

[Unity] Coroutine과 DOTween 차이

Unity로 게임을 만들다 보면"일정 시간 기다렸다가 실행","서서히 투명도 변화","부드럽게 위치 이동"같은 시간 기반 연출을 자주 쓰게 되는데요.그럴 때 자연스럽게 두 가지 기능을 접하게 됩니다.바로 Coroutine(코루틴) 과 DOTween(닷트윈) 입니다.처음에는 "둘 다 뭔가 시간 딜레이 주는 것 같은데, 도대체 뭐가 다른 거지?" 라는 생각이 들었고직접 사용해보면서 그 차이점을 하나씩 체감하게 되었습니다.Coroutine(코루틴)유니티에서 기본으로 제공하는 시간 지연 처리 방식이에요.yield return을 통해 시간이나 조건을 기다리는 식으로,로직의 흐름을 일시정지시키는 것처럼 표현할 수 있습니다.IEnumerator DelayEvent(){ Debug.Log("3초 후 실행됩니다."..

[Unity]일일 및 주간 리셋 타이머 구현

전체적인 동작 흐름우선 전체 흐름을 간단히 살펴보면 다음과 같습니다. → 최초로 타이머 계산→ 코루틴 시작→ 매 초마다 리셋 시간이 되었는지 확인→ 리셋 시간이 되면 이벤트 호출 및 다음 리셋 스케줄링→ 남은 시간을 UI에 표시ScheduleNextDailyReset()private void ScheduleNextDailyReset(){ DateTime now = DateTime.Now; var todayNine = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0); nextDailyResetTime = now 역할:매일 정해진 시각(여기서는 오전 0시)을 기준으로 다음 리셋 시각을 설정합니다.상세 설명:현재 시간이 오전 0시 전이라면 당일 0..

[Unity] 강화카드 중복 제한 로직 구현 및 딕셔너리 기반 구조 개선하기

구현 배경타워 디펜스류 게임에서 강화카드를 사용하여 타워의 능력치를 상승시키는 시스템을 만들었습니다.하지만 개발 도중 다음과 같은 문제가 발생했는데요.같은 강화카드를 반복해서 뽑을 경우 능력치가 무한히 상승한다는 문제였습니다.예를 들어 사거리 증가 카드를 계속 뽑는다면, 게임 후반에는 사정거리가 화면 밖까지 닿는 상황도 발생할 수 있었죠.그래서 저는 카드별로 뽑을 수 있는 최대 횟수를 제한하는 구조를 설계하기로 했습니다.기존 방식의 문제처음에는 아래와 같이 SelectedCard() 메서드 내에서 하드코딩된 조건문으로 각각 제한을 걸었습니다:if ((cardKey == 4101 && currentAmount >= 3) || (cardKey == 4103 && currentAmount >= 4) ||..

[Unity] 프로젝트 XSD 중간발표 회고 – 기능 너머의 고민들

오늘은 프로젝트 중간발표 날이었다지금까지 만들었던 시스템을 정리하고, 발표 자료를 준비해 팀원들 앞에서 설명했다.발표는 짧았지만, 그 과정을 통해 무엇을 만들었는지보다어떤 생각으로 만들었고, 어떤 고민이 있었는지를 더 깊이 되돌아보는 시간이 되었다.발표를 준비하며처음 발표 자료를 만들 때는 지금까지 구현한 기능들을 순서대로 나열하고,그 기능이 어떤 역할을 하는지만 간단히 소개하는 방식으로 구성했다.발표에서도 자연스럽게 “이건 이렇게 동작합니다”, “이 기능은 이런 이유로 만들었습니다”라는 식으로 설명했다.하지만 발표 이후 받은 피드백은 예상과 조금 달랐다.단순히 '기능을 소개하는 발표'보다 더 중요한 건,그 기능을 만들 때 어떤 선택을 했고, 왜 그 방법을 택했는지를 설명하는 것이라고 하셨다.예를 들어 ..

[Unity] 타워디펜스 게임에서 2배속 기능과 실시간 타이머 유지 구현

타워디펜스 게임을 만들다 보면적 유닛의 움직임이나 웨이브 진행 속도를 빠르게 하고 싶은 경우가 많습니다.이럴 때 Time.timeScale을 활용한 배속 기능이 유용하지만,실시간으로 흐르는 플레이 타이머까지 함께 빨라져 버리는 문제가 발생합니다.구현 목표버튼 클릭으로 게임 배속을 1배속 ↔ 2배속으로 전환배속 여부와 무관하게 **UI 타이머(GamePlayTimer)**는 실제 시간 기준으로 작동타이머는 게임 진행 시간(분:초)을 표시배속 버튼 구현[SerializeField] private Button speedButton;[SerializeField] private TextMeshProUGUI speedText;private bool isFast = false;private void Start(){ ..