AI 보조 게임 개발

AI에게 Unity 프리팹 일괄 수정을 맡길 때 Dry Run과 Undo 제대로 넣는 법

kr-gamedev 2026. 7. 17. 09:10

AI 보조 게임 개발 개념도 (AI 생성)

라이브 프로젝트에서는 수백 개의 프리팹에 새 컴포넌트를 붙이거나 오래된 설정값을 바꿔야 할 때가 있다. AI 코딩 도구에 요청하면 일괄 수정용 Editor 스크립트는 금방 만들어 준다. 문제는 코드 생성 속도가 아니라 잘못된 변경을 얼마나 빨리 발견하고 되돌릴 수 있느냐다.

안전한 자동화 도구에는 세 가지 장치가 필요하다. 실제 저장 전에 결과를 보여 주는 Dry Run, 같은 작업을 반복해도 결과가 달라지지 않는 멱등성, Unity Undo를 이용한 복구다. 이 조건을 먼저 계약으로 정하면 AI가 만든 코드도 팀 프로젝트에 투입할 수 있다.

1. 작업 범위를 파일 규칙으로 고정한다

“모든 적 프리팹을 수정해 줘”라고 요청하지 말고 검색 위치와 대상 조건을 명시한다.

Assets/Game/Enemies 아래의 Prefab만 검사한다.
EnemyView가 있고 UseOutline이 false인 오브젝트만 변경한다.
Packages와 읽기 전용 에셋은 제외한다.
Dry Run에서는 파일을 저장하지 않는다.
Apply 후 다시 실행하면 변경 건수가 0이어야 한다.

AI에게 구현 방법보다 입력, 출력, 제외 조건을 먼저 주는 것이 중요하다. 특히 폴더 범위가 없으면 샘플 에셋이나 외부 패키지까지 수정할 수 있다.

2. 검사와 적용을 같은 함수에서 분리한다

먼저 변경 계획을 값으로 만든다. 검사 단계에서는 Unity 오브젝트를 건드리지 않는다.

private readonly struct ChangePlan
{
    public readonly string Path;
    public readonly EnemyView Target;
    public readonly Color Before;
    public readonly Color After;

    public ChangePlan(string path, EnemyView target, Color before, Color after)
    {
        Path = path;
        Target = target;
        Before = before;
        After = after;
    }
}

private static IEnumerable<ChangePlan> Scan()
{
    foreach (string guid in AssetDatabase.FindAssets(
                 "t:Prefab", new[] { "Assets/Game/Enemies" }))
    {
        string path = AssetDatabase.GUIDToAssetPath(guid);
        var root = AssetDatabase.LoadAssetAtPath<GameObject>(path);

        foreach (var view in root.GetComponentsInChildren<EnemyView>(true))
        {
            if (view.UseOutline)
                continue;

            yield return new ChangePlan(
                path, view, view.OutlineColor, Color.red);
        }
    }
}

ChangePlan을 로그나 JSON으로 출력하면 사람이 변경 대상을 먼저 검토할 수 있다. AI에게도 이 결과만 전달해 누락과 과잉 선택을 다시 분석시킬 수 있다.

3. Dry Run은 저장 API를 호출하지 않는다

Dry Run을 단순한 확인 창으로 구현하면 부족하다. 이 경로에서는 SetDirty, SaveAssets, 필드 대입을 호출하지 않아야 한다.

private static void Preview(IReadOnlyCollection<ChangePlan> plans)
{
    foreach (var plan in plans)
        Debug.Log($"[DRY RUN] {plan.Path}: {plan.Before} -> {plan.After}");

    Debug.Log($"변경 예정: {plans.Count}건");
}

프리팹 경로, 컴포넌트 이름, 이전 값과 이후 값을 함께 남겨야 리뷰가 가능하다. 건수만 출력하는 리포트는 잘못된 대상을 찾는 데 도움이 되지 않는다.

4. Apply에는 Undo와 저장을 묶는다

검토가 끝난 계획만 적용한다. 여러 오브젝트를 하나의 Undo 작업으로 묶으면 실수했을 때 한 번에 되돌릴 수 있다.

private static void Apply(IReadOnlyCollection<ChangePlan> plans)
{
    int group = Undo.GetCurrentGroup();
    Undo.SetCurrentGroupName("Enemy Prefab Outline Migration");

    try
    {
        foreach (var plan in plans)
        {
            Undo.RecordObject(plan.Target, "Update EnemyView");
            plan.Target.UseOutline = true;
            plan.Target.OutlineColor = plan.After;
            EditorUtility.SetDirty(plan.Target);
        }

        AssetDatabase.SaveAssets();
    }
    finally
    {
        Undo.CollapseUndoOperations(group);
    }
}

대량 작업 전에는 버전 관리 상태도 깨끗하게 만들어야 한다. Undo는 편집기 안의 안전망이고, Git 변경 목록은 파일 단위의 최종 안전망이다.

5. 멱등성은 재실행으로 검증한다

마이그레이션 도구는 현재 값이 목표 상태와 같으면 반드시 건너뛰어야 한다. “실행할 때마다 컴포넌트 추가”, “목록에 같은 항목 다시 삽입” 같은 코드는 금지한다.

검증 방법은 단순하다. Dry Run에서 예상 건수를 확인하고 Apply를 실행한 뒤 다시 Dry Run을 실행한다. 두 번째 결과가 0건이 아니라면 조건식이나 중복 방지 로직이 잘못된 것이다.

6. AI에게 결과물이 아니라 검증 절차까지 요청한다

좋은 프롬프트는 “Editor 스크립트를 작성해 줘”로 끝나지 않는다. 다음 항목을 완료 조건으로 붙인다.

컴파일 오류가 없어야 한다.
Dry Run에는 쓰기 작업이 없어야 한다.
Apply는 Undo 한 단계로 복구되어야 한다.
두 번째 실행의 변경 건수는 0이어야 한다.
변경된 프리팹 경로를 모두 출력해야 한다.

이렇게 요청하면 AI는 단발성 코드 조각보다 반복 실행 가능한 내부 도구를 만들 가능성이 높아진다. 생성된 코드는 작은 샘플 폴더에서 먼저 실행한 뒤 전체 범위로 확대한다.

마무리 체크리스트

☐ 검색 폴더와 제외 대상을 명시했는가
☐ 검사 단계와 적용 단계를 분리했는가
☐ Dry Run에서 에셋을 수정하거나 저장하지 않는가
☐ 변경 전후 값과 프리팹 경로를 출력하는가
☐ Apply 작업을 Unity Undo로 복구할 수 있는가
☐ 재실행했을 때 변경 건수가 0인가
☐ 전체 적용 전 작은 샘플과 Git 변경 목록을 검토했는가