메인 콘텐츠로 건너뛰기

"Tutorial" 태그의 게시물 5개 게시물건

Step-by-step tutorials

모든 태그 보기

시간 기반 이벤트: 코루틴이 지연과 반복에 적합하지 않은 이유

TinyGiants
GES Creator & Unity Games & Tools Developer

수류탄이 착지한 후 2초 뒤에 폭발을 지연시켜야 합니다. 충분히 간단합니다. 코루틴을 작성합니다. IEnumerator DelayedExplosion(), yield return new WaitForSeconds(2f), 폭발 로직 호출. 깔끔하게 정리하면 10줄 정도. 기분이 좋습니다.

그런데 디자이너가 "플레이어가 폭탄을 해제할 수 있어야 해요"라고 합니다. 좋아요, 이제 StopCoroutine()을 호출할 수 있도록 Coroutine 레퍼런스를 저장해야 합니다. 잠깐 — 코루틴이 시작되기 전에 해제하면? null 체크가 필요합니다. 대기 중에 게임 오브젝트가 파괴되면? 또 다른 null 체크. 코루틴이 완료되는 정확한 프레임에 해제하면? 경쟁 조건. 10줄이 25줄이 됐고, "해제 메시지 vs. 폭발 표시" 분기 처리는 시작도 하지 않았습니다.

이것이 Unity의 모든 시간 기반 이벤트의 이야기입니다. 첫 번째 구현은 깔끔합니다. 두 번째 요구사항이 코드를 두 배로 늘립니다. 세 번째는 직업 선택을 의심하게 만듭니다.

기획자가 코드 없이 이벤트를 설정한다: 디자이너와 프로그래머의 협업 문제

TinyGiants
GES Creator & Unity Games & Tools Developer

화요일 오후 3시. 디자이너가 다가와서 말합니다. "저기, 플레이어가 50 이상 데미지를 받을 때 화면 흔들림을 좀 더 강하게 할 수 있어요? 그리고 히트 사운드 전에 0.5초 딜레이 넣어주세요. 아, 독 효과 틱도 2초 대신 1.5초로 바꿔주세요."

세 가지 변경. 디자이너 입장에서는 15초면 결정할 수 있는 내용입니다. 하지만 실제로 벌어지는 일은 이렇습니다: Scene 뷰를 닫고, IDE를 열고, 로딩을 기다리고, 데미지 핸들러를 찾고, 메서드 안에 묻혀있는 화면 흔들림 강도 값을 찾아 변경합니다. 그다음 오디오 딜레이를 찾는데 — 그건 다른 클래스에 있습니다. 변경합니다. 그리고 독 코루틴을 찾는데 — 또 다른 클래스에 있고, 틱 간격은 WaitForSeconds 호출 안에 있습니다. 변경합니다. 세 파일 모두 저장하고, Unity로 돌아가서 리컴파일을 기다리고, 테스트합니다.

8분 후, 디자이너가 말합니다. "아, 흔들림은 원래가 나았어요. 그리고 독은 1.8초로 해볼 수 있을까요?"

5분 만에 시작하기: 첫 번째 이벤트 드리븐 시스템 구축

TinyGiants
GES Creator & Unity Games & Tools Developer

"시간 5분밖에 없어요. 이벤트 시스템 동작하는 것만 보여주세요."

그래, 충분하다. 이론 없고, 아키텍처 딥다이브 없고, 다른 접근법과의 비교도 없다. Unity 프로젝트에서 제로부터 동작하는 이벤트 기반 인터랙션까지, 빠르게 하고 싶다. 가보자.

이 가이드는 Unity 프로젝트가 열려있고(2021.3 LTS 이상) 약 5분이 있다고 가정한다. 끝나면, 게임에서 뭔가 일어났을 때 발생하는 이벤트가 완전히 별개의 GameObject에서 응답을 트리거하는 것을 갖게 된다 — 둘 사이에 직접 참조 제로.

이벤트 200개 돌파: 이벤트 관리가 무너지는 이유

TinyGiants
GES Creator & Unity Games & Tools Developer

새 Unity 프로젝트를 시작한다. 이벤트 10개를 만든다. OnPlayerDeath, OnScoreChanged, OnLevelComplete. 적절한 이름을 붙이고, 폴더에 넣고, 넘어간다. 인생이 좋다. 전체 이벤트 구조를 머릿속에 담을 수 있다.

6개월이 지났다. 이벤트가 200개다. Project 창은 ScriptableObject 파일의 벽이다. OnPlayerHealthDepleted가 필요한데 — 아니면 OnPlayerHPLow였나? 아니면 OnPlayerHealthZero? 전부 OnPlayer로 시작하는 이름들을 눈을 가늘게 뜨고 스크롤한다. 3분 후 포기하고 새로 하나 만든다, 원하는 이벤트가 이미 있는지조차 확신이 안 서니까.

모든 이벤트 기반 Unity 프로젝트가 결국 도달하는 곳이다. 이벤트 패턴이 잘못돼서가 아니라, 아무도 규모에서 이벤트를 관리하기 위한 도구를 만들지 않았기 때문이다. Unity는 Animation 창, Shader Graph, Timeline, Input System 디버거를 제공한다. 이벤트에는... Project 창뿐이다.

Unity 제네릭 직렬화의 벽: 타입 안전한 이벤트에 보일러플레이트 세금은 불필요하다

TinyGiants
GES Creator & Unity Games & Tools Developer

GameEvent<T>를 만들었다. 깔끔하고, 타입 안전하고, 우아하다. 체력 업데이트용 GameEvent<float> 필드를 만들고 [SerializeField]를 붙였다. Inspector로 전환했다. 필드가 안 보인다. 그냥... 없다. Unity가 0으로 나누기를 요청한 것처럼 빈 패널로 쳐다보고 있다.

Unity의 가장 오래된 아키텍처 두통이다. 직렬화 시스템이 제네릭을 이해하지 못한다. 한 번도 이해한 적 없다. 타입 안전하고 데이터 기반인 이벤트 시스템을 만들려고 시도한 모든 개발자가 이 벽에 정면으로 부딪혔다.

사소한 불편이 아니다. 아키텍처 전체를 오염시키는 종류의 제한이다. 타입 안전성을 포기하거나, 보일러플레이트에 익사하거나, 아름다운 제네릭 설계가 Inspector에 절대 닿지 못한다는 걸 받아들여야 한다. 수년간 커뮤니티의 답은 "그냥 구체 클래스를 직접 작성해라"였다. 그런데 보일러플레이트가 100% 예측 가능하다면, 왜 사람이 쓰고 있는 건가?