장재원Jaewon Chang

장재원Jaewon Chang

Unity 게임 클라이언트 개발자

이화여자대학교 컴퓨터공학과 · 2026.09 졸업

개발부터 출시까지, 변화에 유연하게 적응하는 클라이언트 개발자

PC 미스터리 어드벤처, 모바일 탄막 슈팅, 발달장애 아동을 위한 기능성 게임, LLM 에이전트가 움직이는 시뮬레이션까지 — 장르와 플랫폼이 다른 프로젝트에서 Unity 클라이언트를 맡아 왔습니다. 대표작 KILLA에서는 팀의 유일한 프로그래머로 모든 코드를 맡아 TOEI Games 퍼블리싱과 수상·선정 12건까지 이끌었고, 그 과정에서 최적화·배포·QA까지 출시의 전 과정을 경험했습니다. 생성형 AI가 등장한 뒤에는 LLM NPC를 게임에 적용하고, Claude를 Unity 에디터에 연결해 일하는 방식 자체를 바꿔 왔습니다.

대표 프로젝트

전체 기록

20개 항목

2026
2025
2024
2023
2022
2021

연락처

함께 일할 기회를 기다립니다.

상세

프로젝트

KILLA

한국형 미스터리 비주얼노벨 어드벤처. 팀의 유일한 프로그래머로 게임의 모든 코드를 작성하고, TOEI 퍼블리싱 계약 이후 최적화·배포·QA까지 출시 과정을 맡았습니다. 국내외 수상·선정 12건.

기간
2022.07 – 진행 중
역할
단독 프로그래머 — 게임 전체 코드 작성
팀
검귤단 (Black Tangerine) — 프로그래머 1인
기여
프로그래밍 100%

핵심 성과

  • 팀 내 유일한 프로그래머 — 시스템 설계부터 툴, 빌드, 출시 대응까지 게임의 모든 코드를 직접 작성
  • 2026년 4월 TOEI Games와 퍼블리싱 계약, GIGDC 대상 · SQOOL Award 대상 · GYAAR Studio 2등 등 수상·선정 12건
  • 단방향 진행 구조를 회차 플레이 구조로 8개월 만에 전면 개편 — 씬 30개 이상을 약 15개로 재구성
  • Claude와 원인을 분석하고 A/B 측정으로 검증해 시작 시 멈춤 제거 — 노이즈 생성 352ms → 0ms
  • Claude와 빌드 리포트를 분석해 압축되지 않던 이미지 1,645장을 자동 변환 — 설치 용량 6.4GB → 4.7GB(−27%)
  • 기획·사운드 작업이 코드 수정 없이 반영되도록 툴 제작 — 인스펙터 기반 씬 분기, 대사별 효과음 자동 재생
  • 도쿄게임쇼·gamescom·BitSummit·Unite Seoul 등 5개국 전시 30회 이상, Steam 데모 5개 언어 지원

게임 소개

잔혹동화 같은 인형극 세계에서 용의자들의 기억을 들여다보며 진실을 추리하는 미스터리 어드벤처입니다. 장소를 오가며 NPC와 대화하고 단서를 모으며, 선택에 따라 결말이 달라집니다.

기획 방향 — 일반적인 추리 게임은 사건이 일어나면 현장의 증거와 증언을 논리적으로 따져 범인을 찾는 데 집중합니다. KILLA는 범인 찾기보다 인물들 사이의 관계와, 각자가 사건에 얽히게 된 이야기에 집중합니다. 짧은 행복이 갈등과 오해를 거쳐 비극으로 이어지는 과정을 플레이어가 따라가는 구조입니다. 그래서 클라이언트에서는 인물 사이의 관계와 스토리의 흐름을 몰입감 있고 극적으로 연출하고, 플레이어의 선택에 따라 서로 다른 결말로 이어지게 하는 것이 핵심 과제가 되었습니다.

기술 스택

Unity 6 (URP) · C# · PixelCrushers Dialogue System / Save System (Lua 변수) · Spine · FMOD · Cinemachine · Steamworks · Unity MCP + Claude (AI 에이전트 연동)

개발 방식: AI를 개발 도구로 활용

방식 — 출시 준비 단계부터는 Unity MCP로 Claude를 Unity 에디터에 직접 연결해 개발했습니다. 씬·컴포넌트 조회, 스크립트 작성과 리팩터링, 감사용 에디터 툴 제작에 활용했으며, 아래 작업 중 1번의 상태 흐름 전수 조사, 3번의 최적화 감사, 5번의 전역 매니저 점검과 QA 툴 대부분이 이 방식으로 만들어졌습니다.

검증 — AI 결과물을 그대로 믿지 않았습니다. 도구를 사용하며 발견한 한계(중복 메서드 오탐, 코드 실행 기능 미동작, 파일 해시 불일치 시 편집 실패)를 문서로 정리하고, 어떤 작업을 AI에 맡기고 어떤 작업은 직접 확인할지 기준을 세워 팀 워크플로로 만들었습니다. Claude가 제안한 수정도 기존 구조와 맞는지 먼저 검토하고, 프로젝트의 다른 시스템과 같은 패턴을 따르도록 직접 조정했습니다.

결과 — 반복적인 감사·리팩터링 작업은 AI에 맡기고, 구조 설계와 최종 검증에 시간을 집중할 수 있었습니다.

퍼블리싱: 인디 프로젝트에서 상용 출시로

게임개발연합동아리 브릿지에서 시작해 스마일게이트 멤버십에 선정된 KILLA는 국내외 수상·선정 12건으로 완성도를 검증받았고, 2026년 4월 TOEI Games와 퍼블리싱 계약을 맺었습니다. 퍼블리셔와 일하면서 “재미있는 데모”가 아니라 일정 안에 안정적으로 출시되는 빌드를 만드는 것이 클라이언트 개발자의 일이 되었습니다. 아래는 그 과정에서 맡은 일이며, 30회 이상의 전시 이력은 페이지 맨 아래에 정리했습니다.

각 항목의 코드는 접어 두었습니다. 퍼블리싱 중인 상용 프로젝트라 구조가 드러나는 부분만 발췌했으며, 스포일러가 될 수 있는 변수명과 씬 이름, 인스펙터 툴팁과 일부 필드·예외 처리는 제외하고 축약했습니다.

팀 협업: 다른 직군이 기다리지 않게

KILLA는 게임개발연합동아리 브릿지에서 시작해 지금까지 같은 팀(검귤단)으로 이어 온 프로젝트입니다. 프로그래머는 한 명이지만 기획·아트·사운드 팀원과 함께 일하며, 다른 직군의 작업이 프로그래머를 거치지 않고 게임에 반영되는 구조를 만드는 데 집중했습니다.

  • 기획 — 같은 문이라도 스토리 단계·퀘스트·변수에 따라 다른 곳으로 이동하는 분기를 기획자가 인스펙터에서 경로만 추가해 만들 수 있게 설계 (PortalStoryRouter)
  • 사운드 — 대화 데이터에 효과음만 지정하면 대사와 함께 재생되는 툴로, 씬 수정과 반복 입력 없이 사운드를 반영 (6번)
  • 아트 — 이미지 압축 문제의 원인을 찾아 아티스트가 그린 원본의 화면 결과를 바꾸지 않는 방식으로 해결 (3-3)
  • 전시·퍼블리셔 — 30회 이상의 전시에 맞춰 무인 운영이 되는 전시 빌드를 만들고, 퍼블리셔 일정에 맞춰 QA 빌드를 내보냄 (4번)

1. 회차 플레이 구조 전면 개편 (8개월)

문제 — 기획 의도는 엔딩 후 처음부터 다시 플레이하는 회차 구조였지만, Claude로 프로젝트 전체의 상태 흐름을 조사한 결과 실제 구현은 한 번 지나간 장면에 다시 오지 않는다는 전제의 단방향 구조였습니다. 진행 상태가 30개 이상의 씬과 오브젝트에 분산되어 있어, 같은 장면을 다시 지나가면 상태가 어긋났습니다.

해결 — 약 130개 상태 변수의 사용처를 찾는 전수 조사와 점검 도구 제작은 Claude에 맡기고, 새 구조 설계와 최종 판단은 직접 담당했습니다.

  • 30개 이상의 씬을 장소 기준 약 15개로 재구성
  • 흩어진 상태 변수를 대화 시스템의 전역 변수(GLOBAL.XXX)로 통합
  • 스토리 단계에 따라 오브젝트를 전환하는 레이어 구조(StoryLayerController), 세이브 시스템, ScriptableObject 데이터를 새로 설계
  • AI가 작성한 코드 중 프레임 수로 타이밍을 추측하거나 매니저 생성 순서에 의존하는 부분은 복원 완료 이벤트와 명시적 실행 순서로 교체

결과 — 2022년부터 개발해 온 프로젝트를 8개월 만에 회차 플레이 구조로 전면 개편했습니다.

1-1. 코드: 스토리 단계를 데이터로 관리 — StoryLayerController

씬마다 조건문을 분산하는 대신, 스토리 단계 이름과 같은 이름의 오브젝트 묶음만 활성화하는 방식으로 분기를 단순화했습니다. 시나리오가 늘어도 씬에 레이어 오브젝트만 추가하면 되며, 코드는 수정할 필요가 없습니다.

개선 이력: 초기 구현은 세이브 복원이 끝났을 것이라 가정하고 3프레임을 대기한 뒤 적용했습니다. 복원이 늦어지는 씬에서는 잘못된 레이어가 활성화될 수 있는 구조였습니다. 현재는 세이브 시스템의 복원 완료 이벤트(saveDataApplied)에 맞춰 적용하고, 세이브를 거치지 않는 로드에만 폴백으로 대기하도록 변경했습니다. 같은 프로젝트의 스폰 처리와 같은 패턴으로 맞췄고, 단계 이름에 맞는 레이어가 없으면 경고를 출력해 데이터 오타를 즉시 발견할 수 있게 했습니다. 직렬화 필드와 공개 메서드는 유지해 기존 씬과 호출부를 수정할 필요가 없습니다.

코드 보기 — StoryLayerController
public class StoryLayerController : MonoBehaviour
{
    public Transform storyLayersRoot;
    public bool applyOnStart = true;
    [Min(0)] public int fallbackFrameTimeout = 3; // 세이브를 거치지 않는 로드 대비

    private readonly List<GameObject> _layers = new List<GameObject>();
    private readonly HashSet<string> _layerNames = new HashSet<string>(StringComparer.Ordinal);
    private bool _appliedOnce;

    private void Awake()     => BuildCache();
    private void OnEnable()  => SaveSystem.saveDataApplied += HandleSaveDataApplied;
    private void OnDisable() => SaveSystem.saveDataApplied -= HandleSaveDataApplied;

    // 모든 Saver(위치 등) 복원이 끝난 직후 호출됨 → 프레임 수 추측 없이 정확한 시점에 적용
    private void HandleSaveDataApplied()
    {
        if (applyOnStart) ApplyFromLua();
    }

    // 폴백: 복원 이벤트가 오지 않는 일반 씬 로드
    private IEnumerator Start()
    {
        if (!applyOnStart) yield break;
        while (DialogueManager.instance == null) yield return null;
        for (int f = 0; f < fallbackFrameTimeout && !_appliedOnce; f++) yield return null;
        if (!_appliedOnce) ApplyFromLua();
    }

    public void ApplyFromLua()
    {
        if (storyLayersRoot == null) return;
        string step = DialogueLua.GetVariable(StoryVars.StoryStep).asString;

        if (!string.IsNullOrEmpty(step) && !_layerNames.Contains(step))
            Debug.LogWarning($"STORYSTEP '{step}' 에 맞는 레이어가 없습니다.", this); // 데이터 오타 조기 발견

        foreach (var go in _layers)
            go.SetActive(go.name == step); // 현재 단계와 이름이 같은 레이어만 활성화

        _appliedOnce = true;
    }
}

1-2. 코드: 조건부 씬 이동 — PortalStoryRouter

같은 문이라도 스토리 단계, 퀘스트 상태, 변수에 따라 다른 목적지로 이동시켜야 했습니다. 조건이 있는 경로는 배열 순서대로 우선 검사하고, 하나도 맞지 않으면 조건 없는 기본 경로로 이동하도록 설계해, 기획자가 인스펙터에서 경로를 추가하는 것만으로 분기를 만들 수 있게 했습니다.

코드 보기 — PortalStoryRouter
public bool TryResolve(out string scene, out string storyStep, out string spawnId)
{
    scene = storyStep = spawnId = "";
    string current = StoryFlow.GetStoryStep();
    if (string.IsNullOrEmpty(current) || routes == null) return false;

    Route fallback = null;
    foreach (var r in routes)
    {
        if (r == null || !string.Equals(r.fromStoryStep, current, StringComparison.Ordinal))
            continue;

        if (!r.HasCondition)
        {
            // 조건 없는 경로는 기본 분기로 보관 (가장 먼저 만난 것 우선)
            if (fallback == null) fallback = r;
            continue;
        }

        // 조건부 경로: 만족하면 즉시 채택 (배열 순서 = 우선순위)
        if (ConditionMet(r)) { Assign(r, out scene, out storyStep, out spawnId); return true; }
    }

    if (fallback != null) { Assign(fallback, out scene, out storyStep, out spawnId); return true; }
    return false; // 매칭 없음 → 호출부의 기본 이동 처리에 위임
}

private static bool ConditionMet(Route r)
{
    bool varOk   = string.IsNullOrEmpty(r.requiredBoolVariable)
                   || DialogueLua.GetVariable(r.requiredBoolVariable).asBool;
    bool questOk = string.IsNullOrEmpty(r.requiredQuest)
                   || MatchesQuestState(QuestLog.GetQuestState(r.requiredQuest), r.requiredQuestState);
    bool luaOk   = string.IsNullOrWhiteSpace(r.requiredLuaCondition)
                   || Lua.IsTrue(r.requiredLuaCondition);
    return varOk && questOk && luaOk;
}

2. 시점 구조와 연출

  • 콘텐츠에 따라 3D 사이드뷰, 2D 화면, 3인칭 쿼터뷰를 오가는 시점 구조를 구현해 한 가지 시점의 단조로움을 해소
  • Spine 애니메이션과 Cinemachine 카메라 연출로 스테이지를 구성하고, 플레이어가 NPC와 직접 상호작용한다고 느끼도록 콘텐츠별 연출 설계
  • 전시에서 반응이 밋밋한 구간을 찾아 애니메이션과 셰이더를 추가해 긴장감과 깊이감을 보강 — 이후 전시에서 “화면이 풍부해졌다”는 평가
KILLA 기호 조합 장면 연출 KILLA 추리 장면 연출 KILLA 증거 선택 UI 연출

(현재 공개 가능 자료 - Unity 에디터 캡처)

3. 최적화

3-1. 씬 최적화 감사 툴

문제 — 장소(LOC) 씬이 늘어나면서 씬마다 불필요한 컴포넌트, 중복 라이트·볼륨, 미사용 오브젝트가 쌓였고, 수작업으로 확인하기에는 씬 수가 많았습니다.

해결 — 씬을 자동으로 검사해 문제 항목을 리포트하는 에디터 툴 SceneOptimAudit을 만들고, 여러 LOC 씬에 일괄 최적화 패스를 진행했습니다. 구버전 Post Processing Stack v2 설정은 URP Volume Profile로 이관했습니다.

결과 — 최적화 대상을 사람의 감이 아니라 리포트 기준으로 관리하게 되었습니다.

3-2. 시작 시 멈춤 제거 — 노이즈 생성 352ms → 0ms

문제 — 게임을 시작하면 로딩 중 화면이 약 4초간 검게 보이는 현상이 있었습니다. Profiler로 측정하자 그 구간에서 후처리 플러그인(VolFx)이 시작할 때마다 노이즈 이미지를 매번 새로 그리는 작업이 가장 큰 비중을 차지하는 것으로 나타났습니다.

AI 활용 — Claude에게 원인 코드 분석과 개선안 비교를 맡겼습니다. 대안 중 생성 시점만 늦추는 방법은 멈춤이 다른 장면으로 옮겨갈 뿐이라 버리고, 미리 그려 둔 이미지를 불러오는 방법을 선택했습니다.

검증 — 개선 폭을 숫자로 확인하기 위해, 같은 빌드에서 원본과 개선을 번갈아 실행하는 A/B 측정 도구를 만들게 하고 각 3회 측정했습니다. 화면 결과가 원본과 같은지도 픽셀 단위로 비교하게 했습니다.

지표 원본 개선 차이
노이즈 생성 시간 352ms 0ms 제거
시작 직후 두 번째 프레임 766ms 425ms −44%
노이즈 이미지 메모리 16MB 4MB −75%

i7-13700F / RTX 5060, Development 빌드, 1920×1080 기준

시작 직후 두 번째 프레임 Profiler Timeline 전후 비교 시작 직후 두 번째 프레임 Profiler Hierarchy 전후 비교

같은 빌드의 원본(위)과 개선(아래)을 Profiler로 캡처한 시작 직후 두 번째 프레임 — 노이즈 생성 구간(352ms)이 사라짐

발견 — 처음 측정에서는 노이즈 생성 하나가 약 4초를 차지하는 것처럼 보였지만, 실제 비용은 352ms였습니다. 상세 측정 모드(Deep Profiling)가 켜져 있으면 작은 함수를 많이 부르는 코드일수록 실제보다 훨씬 느리게 측정되기 때문입니다(같은 코드가 352ms vs 3,227ms). AI의 분석도, 측정 도구의 숫자도 그대로 믿지 않고 같은 조건에서 다시 재는 원칙을 이 과정에서 세웠습니다.

3-3. 설치 용량 감축 — 6.4GB → 4.7GB (−27%)

문제 — 출시용 빌드가 6.4GB였고, 대부분이 압축되지 않은 이미지였습니다. 압축 설정을 해 두었는데도 용량이 줄지 않고 있었습니다.

AI 활용 — “압축 설정인데 왜 압축이 안 됐는가”를 질문으로 정하고, Claude에게 빌드 리포트와 이미지 설정의 교차 분석을 맡겼습니다. 원인은 이미지 크기가 4의 배수가 아니면 압축이 적용되지 않는 엔진 규칙이었고, 아티스트가 그린 크기를 그대로 쓴 이미지 대부분이 여기에 해당했습니다.

판단 — AI가 제시한 방법 중 이미지 크기를 줄이는 방법은 그림이 미세하게 바뀌어 버렸고, 여러 이미지를 하나로 묶는 방법은 저사양 PC의 메모리가 늘 수 있어 택하지 않았습니다. 대신 가장자리에 투명 여백을 붙여 크기만 맞추고, 화면 위치는 그대로 유지하는 방법을 선택했습니다.

검증 — 1,600여 장을 한꺼번에 바꾸는 작업이라, 자동 처리 도구에 백업·시범 적용(137장)·되돌리기 기능을 먼저 갖추게 한 뒤 전체에 적용했습니다. 결과는 원본과 수치로 비교해 눈으로 구분하기 어려운 수준인지 확인했고, 영상 17개도 화질을 유지하는 선에서 다시 인코딩했습니다.

항목 이전 이후 차이
출시용 빌드 전체 6,418MB 4,675MB −27%
이미지 5,151MB 3,933MB −1,218MB
영상 873MB 349MB −60%
원본, 압축 결과, 차이 8배 확대 비교

왼쪽부터 원본 · 압축 결과 · 차이를 8배 확대한 이미지 — 차이가 거의 보이지 않음

4. 배포 · 빌드 파이프라인

문제 — 전시용, QA용, 출시용 빌드마다 시작 지점과 설정이 달라 매번 수동으로 변경해야 했고, 작은 실수가 빌드 사고로 이어졌습니다.

해결 — BuildConfig로 Normal / GameShow / QA 세 가지 빌드 모드를 분리하고, StartPoint(씬 + 스토리 레이어 + 스폰 위치 + 날짜 + 초기 Lua)로 어느 지점에서든 시작할 수 있게 했습니다. 전시 빌드에는 무인 운영(AttractController, ExpoIdleWatcher)과 요약 씬을, 출시 빌드에는 Steamworks 연동을 넣었습니다.

결과 — 빌드 종류를 설정만으로 전환할 수 있게 되어 BIC 등 전시와 QA 빌드를 코드 수정 없이 내보냈습니다.

4-1. 코드: 어디서든 시작하는 빌드 — BuildConfig.StartPoint

전시·QA 빌드를 코드 수정 없이 만들기 위해, “어디서부터 시작할지”를 씬 + 스토리 단계 + 스폰 위치 + 날짜 + 초기 Lua의 데이터 묶음으로 정의했습니다. ScriptableObject 하나로 Normal / GameShow / QA 모드를 전환합니다.

코드 보기 — BuildConfig.StartPoint
[CreateAssetMenu(fileName = "BuildConfig", menuName = "Game/Build Config")]
public class BuildConfig : ScriptableObject
{
    public enum BuildMode { Normal = 0, GameShow = 1, QA = 2 }

    [Serializable]
    public class StartPoint
    {
        public string sceneName;   // 로드할 씬
        public string storyStep;   // 활성화할 스토리 레이어 이름
        public string spawnId;     // 스폰 포인트 이름
        public bool overrideDay = true;
        [Min(0)] public int day = 0;
        [TextArea(2, 8)] public string seedLua; // 퀘스트·플래그·아이템 초기 상태

        public bool IsValid => !string.IsNullOrEmpty(sceneName);
    }

    [SerializeField] private BuildMode mode = BuildMode.Normal;
    [SerializeField] private StartPoint gameShowStart = new StartPoint();
    [SerializeField, Range(30f, 600f)] private float idleTimeoutSeconds = 300f; // 전시장 무입력 시 복귀

    public bool IsGameShowMode => mode == BuildMode.GameShow;
    public bool IsQAMode => mode == BuildMode.QA;
    public StartPoint GameShowStart => gameShowStart;
}

5. QA · 안정화

문제 — 분기 서사 게임이라 특정 지점을 재현하려면 앞부분 대사를 모두 진행해야 했고, 전역 매니저가 늘면서 중복 생성·초기화 순서 문제가 간헐적으로 발생했습니다.

해결

  • DEBUG_QA 심볼로 묶은 QA 전용 대사 스킵(QADialogueSkipper)과 QA 빌드 모드로 재현 시간을 단축
  • 전역 매니저 14종을 전수 감사 — DontDestroyOnLoad 중복 가드, 실행 순서 정리, Lua 변수명 GLOBAL.XXX 규칙으로 통일
  • GlobalVarAuditor로 대화 데이터베이스의 변수 오탈자·미사용 변수를 자동 검출
  • 세이브/로드 전면 개편: 슬롯 불일치, 씬 전환 중 저장 타이밍, NPC 위치 복원, 대화 중복 재생 문제 해결
  • 프로젝트 손상(URP 렌더러, 스크립팅 심볼, 자막 프리팹) 발생 시 Git 이력으로 복구

결과 — QA가 “처음부터 다시 플레이”가 아니라 “원하는 지점에서 바로 확인”하는 방식으로 바뀌었습니다.

6. 협업 툴: 대사별 FMOD 효과음 자동 재생

문제 — 대사에 맞춰 효과음을 넣으려면 씬에 이벤트를 따로 배치하거나, 대사 노드마다 이벤트를 일일이 입력해야 했습니다. 효과음을 추가하거나 교체할 때마다 씬 수정과 반복 입력 작업이 필요했습니다.

해결 — 대화 데이터베이스의 각 대사 항목에 FMOD 이벤트를 지정해 두면, 그 대사가 시작될 때 자동으로 재생하는 런타임 플레이어 DialogueFmodLocalPlayer를 만들었습니다.

  • RuntimeInitializeOnLoadMethod로 게임 시작 시 스스로 설치 — 씬과 프리팹을 하나도 수정하지 않음
  • 이벤트를 경로가 아닌 GUID로 조회해, FMOD에서 이벤트 이름이나 폴더를 변경해도 연결이 유지됨
  • 2D 원샷 이벤트만 재생하고 다른 이벤트·버스는 제어하지 않아 BGM과 기존 씬 이벤트에 영향 없음
  • 같은 대사가 여러 경로로 중복 통지되어도 한 번만 재생하고, 잘못된 GUID나 로드되지 않은 뱅크는 대화·항목 ID와 함께 경고로 출력

결과 — 효과음 추가·교체가 대화 데이터 수정만으로 끝나, 사운드 작업이 코드나 씬 수정 없이 게임에 즉시 반영됩니다.

코드 보기 — DialogueFmodLocalPlayer.OnLine
// 대사가 준비되는 시점에 해당 항목의 FMOD 이벤트를 재생 (발췌)
private void OnLine(Subtitle subtitle)
{
    var entry = subtitle?.dialogueEntry;
    if (entry?.fields == null || entry.isRoot || entry.isGroup) return;
    if (string.IsNullOrEmpty(Field.LookupValue(entry.fields, GuidField))) return; // 지정 안 된 대사는 기존 방식 그대로

    // 여러 컨트롤러·캐치업 경로로 같은 대사가 두 번 와도 한 번만 재생
    if (ReferenceEquals(lastSubtitle, subtitle) && lastFrame == Time.frameCount) return;
    lastSubtitle = subtitle;
    lastFrame = Time.frameCount;

    if (!TryReadGuid(entry, out var guid)) { Warn(entry, "Invalid event GUID."); return; }

    var description = RuntimeManager.GetEventDescription(guid); // 경로가 아닌 GUID로 조회
    description.isOneshot(out var oneShot);
    description.is3D(out var spatial);
    if (!oneShot || spatial) { Warn(entry, "Only 2D one-shot events are played."); return; }

    description.createInstance(out var instance);
    instance.start();
    instance.release(); // 원샷: 재생이 끝나면 FMOD가 자동 해제
}

게임 시스템

  • 분기 서사 구조 — 스토리 진행 단계를 StoryLayer로 정의하고 StoryLayerController가 레이어별 오브젝트 세트를 전환. PortalStoryRouter / PortalRequirementRouter로 조건부 씬 이동
  • 인벤토리 — 아이템을 ScriptableObject로 정의하고 id 기반으로 관리. 아이템마다 사용 가능한 씬·스토리 단계를 데이터로 지정해, 대화 중 인벤토리를 열어 아이템을 제출하면 그 결과가 대화 변수로 돌아가 분기에 쓰이도록 연결(InventoryDialogueBridge). 세이브 시스템 연동, 대화 데이터에서 소지 여부를 바로 확인하는 Lua 조건 함수, 수량 변경 이벤트로 퀘스트 조건·알림 UI와 연결
  • 호감도 — NPC별 호감도를 대화 시스템 전역 변수로 저장해 세이브·로드와 대화 분기에서 그대로 사용. 하루 행동력 안에서 대화할 NPC를 고르는 구조로, 남은 행동력을 따로 저장하지 않고 “오늘 대화한 NPC 수”로 매번 계산해 세이브 로드 후에도 상태가 어긋나지 않게 설계
  • 추리 콘텐츠 — 장면마다 조작 방식이 다른 추리·퍼즐 미니게임 여러 종 구현 (스포일러 방지를 위해 세부 내용은 생략)
  • 카메라 — Cinemachine Global/Local 카메라 매니저로 컷신 ↔ 플레이 전환, 그룹 대화용 마스터/투샷/클로즈업 연출, Impulse 카메라 셰이크
  • 게임오버 — 콘텐츠별 목숨을 Lua 변수로 관리, 게임오버마다 자동 저장
  • UI — 아이템/퀘스트 분리 알림 큐, QuestCatalog ScriptableObject, 로컬라이제이션 연동 ConfirmDialog, Spine 말하기 애니메이션 홀드

전시 이력 — 30회 이상 · 5개국

해외

  • 도쿄게임쇼 2024 Selected Indie 80 (일본)
  • 도쿄게임쇼 2025 · 2026 (일본) — 2026년은 TOEI Games 부스
  • gamescom 2024 Indie Arena Booth (독일)
  • BitSummit Drift 2024 · BitSummit PUNCH 2026 (일본 교토)
  • Taipei Game Show 2025 (대만)
  • Tokyo Indie Games Summit 2025 (일본)
  • LA COMIC-CON (미국), ANIMAGIC (독일)

국내

  • G-STAR 2023 · 2024 인디 쇼케이스
  • BIC 2023 · 2026 (부산인디커넥트 페스티벌)
  • 버닝비버 2023 · 2024 — 2년 연속 ‘올해의 버닝비버’
  • 플레이엑스포 2024 Indie Arcade
  • Unite Seoul 2026 Legendary & Indie Showcase

외 일러스타 페스, 서울팝콘, GXG, GLS, UGDAP, 도쿄 게임 던전, GAME AiCON 등

이 프로젝트로 받은 수상 · 함께한 활동 13

수상

2025 경기게임오디션 특별 후속지원 1등

역대 경기게임오디션 TOP 10 대상 특별 후속지원 프로그램 1등

기간
2025.12
주최
경기도
결과
1등
  • KILLA
  • 수상
  • 지원사업
수상

GAME AiCON BEST VISUAL

KILLA로 GAME AiCON BEST VISUAL 수상

기간
2025.08
주최
GAME AiCON
결과
BEST VISUAL
  • KILLA
  • 수상
수상

2025 경기게임오디션 Top 2

제20회 경기게임오디션 결선 2위 (플레이엑스포 KINTEX)

기간
2025.05
주최
경기도
결과
2위
  • KILLA
  • 수상
수상

버닝비버 2024 올해의 버닝비버

2년 연속 올해의 버닝비버 수상

기간
2024.12
주최
스마일게이트 퓨처랩
결과
올해의 버닝비버
  • KILLA
  • 수상
  • 전시
수상

SQOOL GAME AWARD 2024 SUMMER 대상

일본 게임 미디어 SQOOL.NET 편집부가 선정하는 게임 어워드 대상. 페이퍼크래프트풍 아트와 스토리로 호평

기간
2024.09
주최
(주)SQOOL
결과
대상
  • KILLA
  • 수상
  • 해외
수상

GIGDC 2024 일반부 제작부문 대상

글로벌 인디게임 제작 경진대회 일반부 제작부문 대상

기간
2024.08
주최
한국콘텐츠진흥원
결과
대상 (문화체육관광부장관상)
  • KILLA
  • 수상
수상

2024 인디크래프트 챌린저 부문 Top 3

인디게임 공모전 인디크래프트 챌린저 부문 TOP 3 — 레벨업상

기간
2024.07
주최
성남시
결과
Top 3 · 레벨업상
  • KILLA
  • 수상
프로젝트

Agent.I — LLM 사이비 마을 게임

Generative Agents를 적용한 Human-like NPC 14명이 스스로 생각하고 움직이는 마을에서, AI가 결정한 NPC의 행동이 게임의 승패를 가르는 사회 시뮬레이션 게임.

기간
2023.09 – 2024.07
역할
클라이언트 개발 — Generative Agents의 Perceive·Act 단계, NPC 이동·대화 연출, LLM 응답 지연 처리, 맵
팀
스윗팡이크루 3인 (이화여대 캡스톤 프로젝트)

핵심 성과

  • 챗봇형 AI NPC를 넘어, LLM이 결정한 NPC의 행동이 게임 승패를 결정하는 구조 (14명 중 7명 이상 집회 참석 시 패배)
  • Generative Agents의 Perceive·Act 단계를 클라이언트에서 담당 — NPC 지각을 서버 형식으로 만들고, 반환된 텍스트 응답을 이동·대화·이모지로 재생
  • LLM 응답 대기 시간을 NPC 루틴과 이모지 연출로 감춰 자연스러운 행동처럼 보이게 처리
  • 서버 없이 로컬 JSON 목업으로 같은 흐름을 재현해, 서버·클라이언트를 병렬로 개발
  • 플레이테스트 24명 중 91.7%가 "생성형 AI NPC가 다채로운 플레이를 제공한다", 95.8%가 "새로운 재미를 느꼈다"고 응답
  • NPC 인터뷰로 검증 — 집회 시간·장소를 알고 있던 NPC 4명 중 3명이 "다른 NPC와의 대화로 소식을 들었다"고 답해, NPC 간 정보 확산을 확인

게임 소개

AI를 섬기는 사이비 종교의 ’나주교’가 8월 1일 자정에 종교 집회를 열려고 합니다. 마을 NPC들은 서로 대화하며 소식을 퍼뜨리고, 14명 중 7명 이상이 집회에 참석하면 플레이어가 패배합니다. 플레이어는 NPC와 자유롭게 대화하며 각자의 페르소나를 알아내고, 퀴즈로 신뢰를 쌓아 종교의 확산을 막아야 합니다. 플레이어도 NPC와 직접 상호작용할 수 있어, NPC들 사이에서 소식이 퍼지는 과정에 끼어들어 흐름을 바꿀 수 있습니다.

기획 방향 — 기존 게임의 NPC는 정해진 선택지로만 대화해, 모든 플레이어가 같은 내용을 보게 되고 세계관의 몰입도가 떨어집니다. 최근의 AI NPC도 대부분 챗봇 단계에 머물러, 말은 자유롭지만 게임에는 아무 영향을 주지 못합니다. Agent.I는 한 단계 더 나아가 AI가 NPC의 행동을 결정하고, 그 행동이 게임의 승패를 바꾸는 구조를 목표로 했습니다. 그래서 클라이언트에서는 AI가 내린 판단을 이동·대화·이모지로 자연스럽게 보여주고, 그 결과가 실제 게임 규칙으로 이어지게 하는 것이 핵심 과제가 되었습니다.

AI 구조: Generative Agents

Stanford의 Generative Agents (Park et al., 2023)를 기반으로, NPC마다 페르소나와 기억을 갖고 LLM으로 사고하게 했습니다. 세 단계 중 Perceive와 Act는 클라이언트에서 담당했고, 기억과 추론(Memory System)은 서버에서 처리했습니다.

단계 내용 담당
Perceive 주변의 다른 NPC, 현재 장소와 시간을 인식 클라이언트 (직접 구현)
Memory System 저장된 기억과 페르소나로 새로운 정보를 추론 서버 (팀원)
Act 장소 이동, 행동(이모지 + 텍스트), 다른 NPC와의 대화 클라이언트 (직접 구현)

LLM이 만들어 내는 결과는 네 가지입니다.

  1. 행동 설명과 이모지 — 예: 교회에 있고 주변에 ’오화가’가 있는 오전 10시의 나주교 → “예배 준비를 하고 있다”
  2. NPC 간 대화 — 나주교가 오화가에게 집회 참여를 권유하고, 그 대화가 다시 기억에 저장되어 다음 행동에 영향
  3. 장소 이동 — “자정에 집회가 있다”는 기억으로 추론해 교회로 이동
  4. 페르소나 기반 대화 — 플레이어의 자유 입력에 NPC가 자기 성격과 기억대로 대답
Agent.I NPC 간 대화 장면

나주교가 오화가에게 집회 참여를 권유하는 장면 — LLM이 생성한 대화를 말풍선으로, 대화 상대를 하단 상태 표시로 보여줌

내 역할: AI의 판단을 게임 속 행동으로

서버의 LLM은 “누가 어디로 가서 무엇을 한다”는 텍스트만 반환합니다. 저는 NPC가 세상을 인식하는 단계(Perceive)와 LLM의 판단을 게임 속 행동으로 바꾸는 단계(Act)를 맡아, 게임 월드와 AI 사이의 데이터를 변환하는 클라이언트 영역을 담당했습니다. (GameManager·NPC·ChatManager 코드의 절반 이상, 맵 담당)

1. Perceive: 지각 데이터 생성

  • NPC 주변을 10° 간격 36방향 레이캐스트로 감지해 근처 NPC를 찾고, 장소 콜라이더로 현재 위치를 갱신
  • 감지한 NPC·거리·장소를 서버의 지각(Perceive) 형식에 맞춰 JSON으로 직렬화

2. Act: 응답을 플레이로 변환

  • LLM 행동 문자열의 <persona> 이름 / <location> 장소 태그를 정규식으로 파싱해 대화와 이동으로 분기
  • LLM이 지정한 장소 이름을 맵의 실제 위치와 연결하고, 대기 시간이 있는 목적지 대기열로 NavMesh 이동 처리
  • 이모지 문자열을 스프라이트로 바꿔 머리 위 말풍선에, 행동 설명을 설명 말풍선에 표시
  • 마주친 두 NPC의 이름을 정렬한 키로 대화 쌍을 관리해, 같은 대화가 중복 재생되지 않도록 처리

2-1. 코드: LLM의 텍스트를 게임 행동으로

서버의 LLM은 행동을 "<persona> 오화가"(오화가와 대화) 또는 "<location> 교회"(교회로 이동) 같은 문자열로 반환합니다. 아래는 이 문자열을 해석해 NPC의 실제 행동으로 바꾸는 부분입니다. (GameManager.cs 원본에서 발췌. 가독성을 위해 디버그 로그를 제외하고 일부 변수명을 축약했습니다)

코드 보기 — GameManager (행동 문자열 해석)
// 1) 행동 문자열에서 태그와 내용을 분리
//    "<persona> 오화가" → ("persona", "오화가") / "<location> 교회" → ("location", "교회")
private (string tag, string content) ExtractTagAndContent(string input)
{
    string pattern = @"<(persona|location)>\s*([^<]*)";
    Match match = Regex.Match(input, pattern);
    if (match.Success)
        return (match.Groups[1].Value.Trim(), match.Groups[2].Value.Trim());
    return (null, null);
}

// 2) 태그에 따라 대화 또는 이동으로 분기 (applyMovement 중)
(string tag, string content) = ExtractTagAndContent(personaList[npcIndex].ActAddress);
if (tag == "persona")
{
    otherNpcIndex = FindNPCIndex(content);
    NPC[npcIndex].isWaiting = true;
    NPC[otherNpcIndex].isWaiting = true;

    // 두 이름을 정렬해 키를 만들어, A→B와 B→A를 같은 대화로 취급
    string me = NPC[npcIndex].gameObject.name;
    string first  = me.CompareTo(content) < 0 ? me : content;
    string second = me.CompareTo(content) < 0 ? content : me;
    string conversationPair = $"{first}-{second}";

    if (!conversationPairs.Contains(conversationPair))
    {
        conversationPairs.Add(conversationPair);
        chatManager.LoadDialogue(personaList[npcIndex].Chat, npcIndex, otherNpcIndex);
    }
}
else if (tag == "location")
{
    NPC[npcIndex].locationTag = true;
    AddLocation(content, npcIndex);
}

// 3) LLM이 말한 장소 이름 → 맵의 실제 위치로 연결해 이동 대기열에 추가
private void AddLocation(string nextLocation, int npcIndex)
{
    foreach (var nl in location)
    {
        if (nl.gameObject.name == nextLocation)
        {
            NPC[npcIndex].AddWaypoint(nl, 10); // 도착 후 10초 머묾
            break;
        }
    }
}

다시 구현한다면

  • 장소와 NPC를 이름 문자열로 매번 순회해 찾는 대신 Dictionary로 교체
  • 같은 두 NPC가 다시 대화할 수 있도록 대화 쌍 기록에 쿨타임 추가
  • LLM이 맵에 없는 장소 이름을 반환하면 가장 가까운 장소로 이동시키는 예외 처리
  • 태그 문자열 대신 정해진 JSON 형식으로 응답을 받아 해석 실패 가능성 줄이기

3. LLM 응답 지연을 자연스럽게

LLM 응답에는 수 초가 걸려, 그대로 기다리면 NPC가 멈춰 서 있는 것처럼 보입니다. 그래서 각 NPC의 페르소나에 하루 루틴이 있다고 가정해 NPC가 루틴대로 움직이게 하고, 루틴을 시작한 뒤 처음 마주친 NPC와 상호작용을 시작할 때는 머리 위 이모지로 생각하는 듯한 연출을 보여 주어, 응답 대기 시간이 로딩이 아니라 캐릭터의 행동처럼 자연스럽게 넘어가도록 했습니다.

4. 서버 없이 동작하는 클라이언트

  • 서버 응답 대신 단계별 로컬 JSON 목업으로 같은 흐름을 재생할 수 있게 만들어, LLM 서버가 완성되기 전부터 클라이언트를 개발하고 테스트

5. 맵과 NPC

  • 2D 타일맵 마을과 LLM이 참조하는 장소 구성, 시간대별 행동 루틴, 방향별 걷기 애니메이션

검증

  • 플레이테스트 (24명) — 91.7%가 “생성형 AI NPC가 다채로운 게임 플레이를 제공한다”, 95.8%가 “생성형 AI가 새로운 재미를 줬다”고 응답
  • NPC 인터뷰 — 게임이 끝난 뒤 NPC에게 직접 질문해 AI가 의도대로 움직였는지 확인
    • 집회에 참석한 NPC 6명 중 4명이 집회 시간과 장소를 알고 있었음
    • 그 4명 중 3명이 “오화가와 대화하다가 소식을 들었다”고 답변 → NPC 사이의 대화로 정보가 퍼진 것을 확인
    • 나주교와 대화한 NPC 3명 모두 나주교를 기억

배운 점

플레이테스트에서 플레이어들은 AI NPC가 주는 새로운 경험에는 크게 반응했지만, 그것이 곧 게임 자체의 재미로 이어지지는 않았습니다. AI의 판단이 승패·이동·연출 같은 게임 규칙과 강하게 연결될 때 비로소 재미가 된다는 것을 배웠고, 이후 AI 캐릭터와 플레이어가 실제로 상호작용하는 게임을 만드는 것이 목표가 되었습니다.

수상

제2회 GYAAR Studio 인디게임 콘테스트 2등

반다이남코의 인디 레이블 GYAAR Studio 공모전. 응모작 236편 중 2등 수상 (TOKYO INDIE GAMES SUMMIT 2024 발표)

기간
2024.03
주최
반다이남코엔터테인먼트·반다이남코스튜디오
결과
2등
  • KILLA
  • 수상
  • 해외
수상

2024 게임기획 지원(예비창업) 선정 및 추가지원

한국콘텐츠진흥원 게임기획 지원(예비창업) 사업 선정, 성과를 인정받아 추가지원 확보

기간
2024.03
주최
문화체육관광부
결과
선정 · 추가지원
  • KILLA
  • 지원사업
수상

버닝비버 2023 올해의 버닝비버

스마일게이트 인디게임 페스티벌 버닝비버 2023 올해의 버닝비버

기간
2023.12
주최
스마일게이트 퓨처랩
결과
올해의 버닝비버
  • KILLA
  • 수상
  • 전시
프로젝트

마법소녀, 도와줘! (Help me, Magical Girl!)

마법소녀들의 힘으로 몰려오는 적을 처치하고 악의 근원인 구멍을 없애는, Y2K 레트로 도트 감성의 모바일 세로형 액션 탄막 슈팅.

기간
2023.03 – 2023.08
역할
클라이언트 개발 — 게임 내 연출 및 UI
팀
마세구(MSG) 7인 — 프로그래머 2 · 기획 2 · 아트 2 · 사운드 1

핵심 성과

  • 클라이언트 프로그래머 2인 중 연출·UI 파트 담당 (탄막 슈팅 시스템은 다른 프로그래머 담당)
  • '복수' 마법소녀 스토리 오프닝 연출과 '명예' 마법소녀 스테이지 1 인게임 UI로 프로토타입 완성
  • 캐릭터 선택 → 스테이지 선택(잠금·클리어 표시) → 인게임(HP·EXP·레벨업 스킬 선택) UI 흐름 구현
  • 한 손 조작 세로형 모바일 화면 기준 UI 설계

게임 소개

어느 날 하늘에 구멍이 생기고, 그 안에서 악마들이 쏟아져 나옵니다. 세상을 구하기 위해 결성된 ‘마법소녀가 세상을 구한다!’, 일명 마.세.구(M.S.G) 협회의 마법소녀들은 각자의 사정을 안고 싸웁니다.

뱀파이어 서바이벌 계열의 액션 탄막 슈팅으로, 스킬은 자동 발사되고 플레이어는 이동과 레벨업 스킬 선택(3개 중 1개, 공격·패시브·조합 스킬)에 집중합니다. 한 손으로 짧게 즐기는 모바일 세로형 게임입니다.

기획 방향 — 이 장르는 같은 전투가 반복되기 쉬워, 마법소녀마다 다른 사연과 시점을 담은 스토리 ’임무’를 더해 반복 피로를 줄이고자 했습니다. 그래서 클라이언트에서는 세로 화면 한 손 조작에 맞춘 UI와, 캐릭터의 사연을 보여주는 스토리 연출이 핵심 과제가 되었습니다.

설계 포인트

  • 같은 시간선을 다른 시점으로 — 마법소녀 3명이 각자 4개 스테이지의 타임라인을 갖고, 같은 번호의 스테이지는 같은 사건을 다른 인물의 시선으로 보여줍니다. 최종 스테이지에서 하나로 합쳐져 총 13개 스테이지.
  • 임무형 미니게임 — 장르 특유의 반복 피로를 줄이기 위해 학교 디펜스, 구멍 점령전, 보물 찾기, 보스전을 스토리 ’임무’로 배치.
  • 캐릭터 고유 스킬 — 예: 인플루언서 마법소녀는 셀카봉 무기와 “스포트라이트”, “이모지 폭격”, “싹둑이(채팅창 관리봇)” 스킬.
  • Y2K 레트로 도트 그래픽과 8bit 기반 밴드 사운드로 “그 시절 우리가 좋아했던 마법소녀” 콘셉트를 구현.

내 역할: 연출 및 UI 개발

  • 오프닝 연출 — ‘복수’ 마법소녀(연보라)의 사연을 담은 스토리 오프닝 구현
  • UI 흐름 — 마법소녀 선택 → 스테이지 선택 화면(미해금 스테이지 자물쇠, 클리어 스테이지 별 표시) → 인게임
  • 인게임 HUD — 캐릭터 하단 체력 바, 상단 경험치 바, 레벨업 시 무기·악세사리 선택지를 강조하는 선택 UI
  • 세로형 모바일 대응 — 한 손 플레이 기준으로 화면 배치

결과

팀 결성 한 달 만에 오프닝과 스테이지 1 인게임이 포함된 플레이 가능한 프로토타입을 완성했습니다.

이 프로젝트로 받은 수상 · 함께한 활동 1

  • Unity
  • C#
  • 모바일
  • 탄막 슈팅
  • UI
  • 연출
  • 팀 프로젝트
수상

BIC 2023 루키 부문 서사 분야 파이널리스트

부산인디커넥트 페스티벌 루키 부문 서사 분야 파이널리스트

기간
2023.08
주최
부산광역시
결과
파이널리스트
  • KILLA
  • 수상
  • 전시
수상

한국콘텐츠진흥원 창의인재육성 우수프로젝트

창의인재육성 프로그램 우수프로젝트로 선정

기간
2023.05
주최
한국콘텐츠진흥원
결과
우수프로젝트 선정
  • KILLA
  • 지원사업
대외활동

브릿지 (게임개발연합동아리)

대학생 연합 게임 제작동아리. KILLA를 처음 시작한 곳이며, 팀 '마세구(MSG)'를 결성해 모바일 탄막 슈팅 '마법소녀, 도와줘!'도 개발.

역할
클라이언트 개발 (연출 · UI)
소속
브릿지 — 게임개발연합동아리
  • 동아리
  • 팀 프로젝트
대외활동

스마일게이트 멤버십

스마일게이트 퓨처랩 창작 지원 프로그램에서 KILLA 개발.

기간
2022.07 – 2022.12
역할
KILLA 팀 (검귤단) 개발
소속
스마일게이트 퓨처랩
  • KILLA
  • 창작지원
대외활동

KING (이화여대 게임개발동아리)

교내 게임개발동아리에서 각종 세미나 진행·참여.

기간
2022.01
소속
이화여자대학교 게임개발동아리 KING

세미나

  • KILLA 개발기 — 인디게임 기획, 개발 그리고 출시까지: 팀 검귤단의 KILLA를 사례로 인디게임의 기획부터 개발, 출시 준비까지의 과정을 공유
  • 동아리
  • 세미나
프로젝트

루루와 치치의 지구적응기

경도 발달장애 아동이 전자레인지 쓰기, 물건 사기, 버스 타기 같은 생활 중심 기능적 기술을 터치·드래그 시뮬레이션으로 익히는 모바일 학습 게임. Google Play 출시, 대학혁신 사례영상 경진대회 대상.

기간
2021.03 – 2021.12
역할
클라이언트 개발 — 시뮬레이션 게임 구현, 플레이테스트, Google Play 출시
팀
게맛살 5인 — 특수교육·국어교육·뇌인지과학·컴퓨터공학 다학제 팀

핵심 성과

  • Google Play 출시 (현재 서비스 종료) — 기획·구현·아동 대상 플레이테스트·런칭까지 한 사이클을 완주
  • 대학혁신 사례영상 경진대회 대상 수상
  • 생활 기능적 기술 8가지를 장소별 시뮬레이션으로 전부 구현 — 특수교사의 '과제 분석'처럼 기술을 단계별로 세분화해 터치·드래그로 완성
  • 실패 경험이 많은 아이들을 위한 동기 부여 구조 — 즉각적 보상(코인·꾸미기), 행동계약서, 부모 칭찬으로 이어지는 실생활 인증 게시판
  • 특수교육·국어교육·뇌인지과학·컴퓨터공학 다학제 팀에서 Unity·C# 개발 담당 (개발자 2인)

게임 소개

마을 지도에서 장소를 골라 전자레인지 쓰기, 물건 사기, 버스 타기 같은 생활 기술을 터치·드래그 시뮬레이션으로 연습하는 모바일 학습 게임입니다. 경도 발달장애가 있는 초등학교 1~4학년 아동이 가정에서 부모와 함께 사용합니다.

기획 방향 — 많은 발달장애 아동은 반복된 실패 경험 때문에 새로운 것을 배우기 전부터 두려움 때문에 시도하지 않지만, 대부분 모바일 게임은 좋아해 휴대폰 사용 시간이 길었습니다. 목표를 달성하면 즉각적인 보상을 주는 게임이라면 아이들이 자신감을 얻고, 실전 전에 생활 기술을 미리 연습할 수 있다고 보았습니다. 코로나19로 대면 수업이 어려워진 상황이라 가정에서도 아이 수준에 맞춰 연습할 수 있는 도구가 필요했습니다. 그래서 클라이언트에서는 특수교사가 기술을 단계별로 나눠 가르치는 방식을 터치·드래그 상호작용으로 옮기고, 아이들이 실패 부담 없이 따라올 수 있도록 보상을 바로 보여주는 것이 핵심 과제가 되었습니다.

게임 구성

마을 지도에서 장소를 고르면, 그곳에서 필요한 생활 기술을 게임으로 연습합니다.

장소 기능적 기술
집 전자레인지로 음식 데우기, 시계 보기
편의점 물건 구매하기
음식점 계산하기, 키오스크 활용하기
대중교통 지하철 타기, 버스 타기
스마트폰 카카오톡으로 대화하기 (상황에 맞는 이모티콘 고르기)
  • 단계별 시뮬레이션 — 특수교사가 기술을 세분화해 가르치는 ‘과제 분석’ 방식을 적용해, 화면 터치와 드래그로 한 단계씩 완성
  • 연습 문제 — 게임이 끝나면 배운 기술을 간단한 문제로 확인하고, 맞히면 코인 지급
  • 보상과 꾸미기 — 출석 보상·일일/주간 퀘스트로 코인을 모아 상점에서 옷을 구매하고 옷장에서 캐릭터 꾸미기
  • 함께 약속해요 (행동계약서) — 아이와 부모가 목표 행동과 원하는 보상을 함께 정하는 기능
  • 게시판 — 아이가 실제 생활에서 기술을 실천한 인증 사진을 올리면 부모가 확인하고 칭찬. 게임 밖의 실생활로 학습을 이어 주는 장치
  • 친구 — 다른 사용자와 메시지와 선물 주고받기

진행 방식: Design Thinking

  1. 공감 — 아동·부모·교육자 설문조사와 심층 인터뷰, 공감 지도 작성
  2. 정의 — 페르소나와 문제 정의문으로 핵심 문제를 정리: “기존 방식은 재미가 없어 집중하기 어렵다”
  3. 아이디어 — 스토리보드, 와이어프레임, 와이어 플로우 차트
  4. 프로토타입 — Adobe XD로 프로토타입을 만든 뒤 Unity·C#으로 기능적 기술 하나를 먼저 구현
  5. 테스트 — 발달장애 아동들이 직접 플레이하는 테스트로 반응을 확인하고, 특수교육·교육공학 교수님의 피드백까지 반영해 수정
  6. 출시 — 8가지 기술을 모두 완성해 Google Play에 출시하고, 부모·교사를 위한 활용 가이드 영상 제작

내 역할: 클라이언트 개발

  • 프로토타입을 바탕으로 Unity·C# 시뮬레이션 게임 구현 — 8가지 기능적 기술 전부 완성
  • 발달장애 아동 대상 플레이테스트 진행과 피드백 반영
  • Google Play 출시까지 런칭 과정 담당

비전공자가 대부분인 팀에서 기획서와 XD 프로토타입을 실제로 동작하는 게임으로 옮기는 역할이었습니다. 특수교사를 준비하는 팀원들의 교수 방식(과제 분석, 즉각적 강화)을 게임의 상호작용과 보상 구조로 옮기며 사용자를 먼저 이해하고 그에 맞춰 구현하는 방법을 익혔고, 기획부터 출시까지의 전 과정을 처음으로 완주했습니다.

이 프로젝트로 받은 수상 · 함께한 활동 1

  • Unity
  • C#
  • 모바일
  • 기능성 게임
  • 접근성
  • Design Thinking
  • 팀 프로젝트
수상

대학혁신 사례영상 경진대회 대상

발달장애 아동의 생활 기능 학습 게임 '루루와 치치의 지구적응기'로 전국 대학 대상 사례영상 경진대회 대상 수상

기간
2021.07
주최
대학혁신지원사업 총괄협의회
결과
대상