728x90
728x90
[ 게임 개발/Unity 6 & C# ][Unity/C#] Unity 6(6.3) FSM과 가비지 컬렉션(GC) 0MB 최적화 기법: 시즌 1 36명 캐릭터 FSM과 수백 개 오브젝트 무가비지 풀링 아키텍처2026-11-10 21:57:13TL;DR1. Unity 6(Unity 6.3) 환경에서 방치형 클리커의 다중 엔티티 동시 제어 시 발생하는 프레임 드랍의 주원인은 빈번한 Instantiate/Destroy와 상태 전환 델리게이트 힙 할당입니다.2. 상태 패턴(State Pattern) FSM을 정적 인스턴스로 캐싱하고, 큐(Queue) 기반 오브젝트 풀링을 결합하여 프레임당 가비지 컬렉션(GC) 할당량을 0바이트(0B)로 수렴시켰습니다.3. 본 포스팅에서는 모바일 저사양 기기에서 60FPS를 항시 유지하기 위한 C# 무가비지 FSM 아키텍처와 실측 벤치마크 데이터를 정리합니다. 1. 문제 정의: 멀티 엔티티 동시 구동 시 GC Spike 발생 원인쿠고랑 (kugorang)의 모바일 방치형 게임 은 시즌 1에 등장하는 12개 패밀리 총..
[ 게임 개발/Unity 6 & C# ][Unity/C#] 방치형 클리커 최적화: 600명 객체 풀링과 Queue 기반 무한 순환 FSM 설계 (Garbage Collection 0회 달성)2026-11-09 21:23:44TL;DR• 문제 정의 — 모바일 클리커 환경에서 600명의 손님 인스턴스를 동적으로 생성·파괴하면 힙 메모리 단편화와 가비지 컬렉터(GC) 실행으로 프레임 드롭(16.6ms 초과)이 발생합니다.• 아키텍처 해법 — Queue 기반 순환 인덱스 버퍼, 600개 경량 데이터 구조체 사전 풀링(Object Pooling), 4단계 유한 상태 머신(FSM)을 구축했습니다.• 실측 검증 결과 — 인게임 런타임 중 캐릭터 순환 관련 힙 할당 0 Bytes, GC 수거 0회 유지, 저사양 안드로이드 기기에서 60FPS를 방어했습니다.1. 개요 및 병목 현상 분석쿠고랑 (kugorang)의 방치형 클리커 게임 은 600종의 고유 손님 데이터가 순차적으로 고물상 화면에 진입해 터치 입력을 처리하고 퇴장하는 루프 구조를..
[ 게임 개발/Unity 6 & C# ][Unity] ML-Agents로 구현하는 강화학습 게임 AI: 관찰·행동·보상 설계부터 학습 파이프라인까지2025-10-25 20:38:11TL;DR — 3줄 핵심 요약• 문제: 조건문으로 NPC를 짜면 상태(체력, 적 위치, 탄약, 부상병 수)가 늘어날수록 경우의 수가 곱으로 늘어나고, 개발자가 넣지 않은 조합에서 NPC는 아무 행동도 하지 못한다.• 기술/원인: ML-Agents는 상태를 숫자 배열(관찰)로 넘기고, 신경망이 출력한 행동 값을 받아 실행한 뒤, 그 결과로 보상 숫자를 돌려주는 루프를 반복한다. 신경망의 가중치는 PPO 같은 알고리즘이 누적 보상을 키우는 방향으로 조금씩 수정한다.• 해결/인사이트: 결과를 좌우하는 것은 알고리즘이 아니라 보상 함수다. 휴리스틱 모드로 환경이 정상인지 먼저 확인하고, 강화학습으로 정책을 학습시키고, 시범 데이터가 있으면 모방학습으로 출발점을 앞당기는 순서가 실전에서 가장 빠르다.ML-Agen..
[ 게임 개발/Unity 6 & C# ][Unity C#] 비동기 프로그래밍 완벽 가이드: Coroutine vs Thread vs UniTask(Awaitable) 비교2025-07-30 02:56:57TL;DR — 3줄 핵심 요약• 문제: "1초 뒤 실행" 하나를 하려고 코루틴을 쓰는지, Thread를 쓰는지에 따라 프레임이 멈추기도 하고 예외가 나기도 한다. 셋 다 비동기처럼 보이지만 실행 위치가 다르다.• 기술/원인: Coroutine은 컴파일러가 메서드를 상태 머신 클래스로 바꾸고, Unity가 매 프레임 MoveNext()를 호출해 이어서 실행한다. 메인 스레드에서 돌므로 Unity API를 쓸 수 있지만 병렬 실행은 아니다. Thread는 OS가 코어에 배정하는 별도 실행 흐름이다. Unity API는 메인 스레드에서만 안전하다.• 해결/인사이트: 프레임 타이밍과 Unity API가 필요하면 Coroutine(또는 Awaitable/UniTask), CPU를 오래 쓰는 계산은 Job Syst..
[ 게임 개발/Unity 6 & C# ][게임 디자인 패턴] Unity C# vs Unreal C++ 옵저버 패턴(Observer Pattern) 실전 구현과 UML 비교2025-06-01 17:16:08TL;DR — 3줄 핵심 요약• 문제: 체력이 바뀔 때 UI, 사운드, 업적이 모두 반응해야 한다. 체력 클래스가 UI와 업적을 직접 호출하면, 화면을 하나 추가할 때마다 체력 클래스 코드를 고쳐야 하고 서로를 참조하는 코드가 늘어난다.• 기술/원인: 옵저버 패턴은 "알림을 받을 함수의 목록"을 값으로 보관한다. C#은 delegate와 event로, C++은 멤버 함수 포인터와 객체 주소를 묶은 델리게이트로 이 목록을 만든다. 발행자는 목록을 순서대로 호출할 뿐, 누가 등록했는지 모른다.• 해결/인사이트: 구독과 해제를 반드시 짝으로 둔다(OnEnable/OnDisable, BeginPlay/EndPlay). 해제하지 않은 구독은 파괴된 객체의 함수를 계속 호출해 오류를 만든다.옵저버 패턴이 없을 때 ..
[ 게임 개발/Unity 6 & C# ][게임 엔진 비교] Unity C# vs Unreal C++ 아키텍처 비교: 메모리 관리, GC, 성능 및 생산성 분석2025-03-31 20:35:15들어가며학교 과제로 Unity Engine에서 C#이 쓰이게 된 이유와 Unreal Engine에서 C++이 쓰이게 된 이유, 그리고 이 둘 간의 비교하는 리포트를 작성하게 되었다. 글의 품질이 나쁘지 않아서 블로그에도 포스팅을 해본다. Unity 엔진과 C#게임 클라이언트 개발 도메인 정의게임 클라이언트 개발은 사용자의 기기에서 실행되는 게임 프로그램을 제작하는 작업이다. 3D/2D 그래픽 렌더링, 물리 엔진, 사용자 입력 처리, AI, 게임 플레이 로직과 같은 복잡한 실시간 처리가 필요하다. 이런 도메인에서는 높은 성능과 메모리 효율성이 핵심이다. 게임은 프레임 단위로 작동하며 매 순간 방대한 연산을 처리해야 하기 때문에, 프로그래밍 언어의 실행 속도와 하드웨어 제어 능력이 매우 중요하다.[^1] 더..
[ 게임 개발/Unity 6 & C# ]Unity UI Toolkit을 활용한 Custom Package 만들기 (3)2023-05-21 22:31:15TL;DR — 3줄 핵심 요약• 문제: UI Toolkit으로 만든 에디터 창이 저장이 안 되고, 키 입력이 많아지면 쓰기 불편했고, 패키지로 묶으니 경로가 깨졌다.• 기술/원인: 원인은 세 가지였다. 데이터 객체가 struct라서 복사본만 바뀐 점, Foldout이 기본으로 펼쳐진 점, UXML 경로가 Assets 기준 절대 경로였는데 패키지는 Packages 아래에 놓이는 점이다.• 해결/인사이트: struct를 class로 바꾸고, 접힌 Foldout 하나로 묶고, 시작할 때 AssetDatabase에서 경로를 찾게 고쳤다. 코드 수정과 검증은 따로 해야 하며, 버튼 상태 경우의 수는 실제로 눌러 보며 확인했다.들어가며: 시리즈 마지막 글1편에서 계기와 목표를, 2편에서 진행 방식과 도구를 정리했다..
[ 게임 개발/Unity 6 & C# ]Unity UI Toolkit을 활용한 Custom Package 만들기 (2)2023-04-29 19:22:00TL;DR — 3줄 핵심 요약• 문제: 두 달 안에 낯선 기술로 Unity 에디터 도구를 만드는 사이드 프로젝트에서 일정과 결과를 함께 잡아야 했다.• 기술/원인: 처음부터 범위를 잘랐다(PC와 키보드·마우스만). 기록은 GitHub Issue와 Discussion에, 사소한 대화는 Discord에 남겼다. 코드 초안은 ChatGPT 3.5로 만들었다.• 해결/인사이트: 마감은 2월 말에서 3월 중순으로 밀렸지만 기능은 끝냈다. ChatGPT는 구조를 잡는 데 도움이 됐고, 없는 API를 있는 것처럼 쓰는 환각 때문에 코드를 통째로 쓰지는 못했다.들어가며: 2편에서 다루는 것1편에서는 프로젝트를 시작한 계기와 목표, 역할을 정리했다. 2편에서는 진행 방식과 새로 쓴 기술에서 좋았던 점과 아쉬웠던 점을 정..
728x90
728x90