Unity + Koog: Kotlin 에이전트에서 게임 구동

·3분 읽기

원문: Koog Documentation — UnityMcp 이 글은 Koog 공식 문서의 UnityMcp 페이지를 한국어로 옮긴 번역본입니다. 문서 구조와 링크 의미를 유지하되, MkDocs 전용 UI 문법은 블로그에서 읽기 좋도록 정리했습니다.

Unity + Koog: Kotlin 에이전트에서 게임 구동

:material-github: Open on GitHub{ .md-button .md-button--기본 } :material-download: Download .ipynb{ .md-버튼 }

이 노트북은 MCP(Model Context Protocol)를 사용하여 Koog로 Unity에 능숙한 AI 에이전트를 구축하는 과정을 안내합니다. Unity MCP 서버에 연결하고, 도구를 검색하고, LLM으로 계획하고, 공개 장면에 대한 작업을 실행합니다.

전제 조건

  • Unity-MCP 서버 플러그인이 설치된 Unity 프로젝트 -JDK 17+
  • OPENAI_API_KEY 환경 변수의 OpenAI API 키
1%useLatestDescriptors2%use koog3
1lateinit var process: Process2

1) OpenAI API 키 제공

OPENAI_API_KEY 환경 변수에서 API 키를 읽어 노트북 외부에 비밀을 유지할 수 있습니다.

1val token = System.getenv("OPENAI_API_KEY") ?: error("OPENAI_API_KEY environment variable not set")2val executor = simpleOpenAIExecutor(token)

2) Unity 에이전트 구성

Unity용 컴팩트 시스템 프롬프트와 에이전트 설정을 정의합니다.

1val agentConfig = AIAgentConfig(2    prompt = prompt("cook_agent_system_prompt") {3        system {4            "You are a Unity assistant. You can execute different tasks by interacting with tools from the Unity engine."5        }6    },7    model = OpenAIModels.Chat.GPT4o,8    maxAgentIterations = 10009)
1

3) Unity MCP 서버 시작

Unity 프로젝트 디렉터리에서 Unity MCP 서버를 시작하고 stdio를 통해 연결합니다.

1// https://github.com/IvanMurzak/Unity-MCP2val pathToUnityProject = "path/to/unity/project"3val process = ProcessBuilder(4    "$pathToUnityProject/com.ivanmurzak.unity.mcp.server/bin~/Release/net9.0/com.IvanMurzak.Unity.MCP.Server",5    "60606"6).start()

4) Koog에서 연결하고 에이전트를 실행합니다.

Unity MCP 서버에서 도구를 검색하고, 작은 계획 우선 전략을 구축하고, 열려 있는 장면을 수정하기 위해 도구만 사용하는 에이전트를 실행합니다.

1import kotlinx.coroutines.runBlocking23runBlocking {4    // Create the ToolRegistry with tools from the MCP server5    val toolRegistry = McpToolRegistryProvider.fromTransport(6        transport = McpToolRegistryProvider.defaultStdioTransport(process)7    )89    toolRegistry.tools.forEach {10        println(it.name)11        println(it.descriptor)12    }1314    val strategy = strategy<String, String>("unity_interaction") {15        val nodePlanIngredients by nodeLLMRequest(allowToolCalls = false)16        val interactionWithUnity by subgraphWithTask<String, String>(17            // work with plan18            tools = toolRegistry.tools,19        ) { input ->20            "Start interacting with Unity according to the plan: $input"21        }2223        edge(24            nodeStart forwardTo nodePlanIngredients transformed {25                "Create detailed plan for " + agentInput + "" +26                    "using the following tools: ${toolRegistry.tools.joinToString("\n") {27                        it.name + "\ndescription:" + it.descriptor28                    }}"29            }30        )31        edge(nodePlanIngredients forwardTo interactionWithUnity onAssistantMessage { true })32        edge(interactionWithUnity forwardTo nodeFinish)33    }3435    val agent = AIAgent(36        promptExecutor = executor,37        strategy = strategy,38        agentConfig = agentConfig,39        toolRegistry = toolRegistry,40        installFeatures = {41            install(Tracing)4243            install(EventHandler) {44                onAgentStarting { eventContext ->45                    println("OnAgentStarting first (strategy: ${strategy.name})")46                }4748                onAgentStarting { eventContext ->49                    println("OnAgentStarting second (strategy: ${strategy.name})")50                }5152                onAgentCompleted { eventContext ->53                    println(54                        "OnAgentCompleted (agent id: ${eventContext.agentId}, result: ${eventContext.result})"55                    )56                }57            }58        }59    )6061    val result = agent.run(62        " extend current opened scene for the towerdefence game. " +63            "Add more placements for the towers, change the path for the enemies"64    )6566    result67}

5) MCP 프로세스 종료

실행이 끝나면 항상 외부 Unity MCP 서버 프로세스를 정리하십시오.

1// Shutdown the Unity MCP process2process.destroy()