Unity + Koog: Kotlinエージェントでゲームを動かす
Open on GitHub Download .ipynb
このノートブックでは、Model Context Protocol (MCP) を使用してKoogでUnityに精通したAIエージェントを構築する手順を説明します。Unity MCPサーバーに接続し、ツールを検出し、LLMで計画を立て、開いているシーンに対してアクションを実行します。
前提条件
- Unity-MCPサーバープラグインがインストールされたUnityプロジェクト
- JDK 17以降
- 環境変数
OPENAI_API_KEY
に設定されたOpenAI APIキー
kotlin
%useLatestDescriptors
%use koog
kotlin
lateinit var process: Process
1) OpenAI APIキーを提供する
APIキーは環境変数 OPENAI_API_KEY
から読み込まれるため、ノートブックからシークレットを分離できます。
kotlin
val token = System.getenv("OPENAI_API_KEY") ?: error("OPENAI_API_KEY environment variable not set")
val executor = simpleOpenAIExecutor(token)
2) Unityエージェントを構成する
Unity向けに、コンパクトなシステムプロンプトとエージェント設定を定義します。
kotlin
val agentConfig = AIAgentConfig(
prompt = prompt("cook_agent_system_prompt") {
system {
"You are a Unity assistant. You can execute different tasks by interacting with tools from the Unity engine."
}
},
model = OpenAIModels.Chat.GPT4o,
maxAgentIterations = 1000
)
kotlin
3) Unity MCPサーバーを起動する
UnityプロジェクトディレクトリからUnity MCPサーバーを起動し、stdio経由で接続します。
kotlin
// https://github.com/IvanMurzak/Unity-MCP
val pathToUnityProject = "path/to/unity/project"
val process = ProcessBuilder(
"$pathToUnityProject/com.ivanmurzak.unity.mcp.server/bin~/Release/net9.0/com.IvanMurzak.Unity.MCP.Server",
"60606"
).start()
4) Koogから接続してエージェントを実行する
Unity MCPサーバーからツールを検出し、小さなプラン優先戦略を構築し、開いているシーンを変更するためにツールのみを使用するエージェントを実行します。
kotlin
import kotlinx.coroutines.runBlocking
runBlocking {
// MCPサーバーのツールでToolRegistryを作成します
val toolRegistry = McpToolRegistryProvider.fromTransport(
transport = McpToolRegistryProvider.defaultStdioTransport(process)
) + ToolRegistry {
tool(ProvideStringSubgraphResult)
}
toolRegistry.tools.forEach {
println(it.name)
println(it.descriptor)
}
val strategy = strategy<String, String>("unity_interaction") {
val nodePlanIngredients by nodeLLMRequest(allowToolCalls = false)
val interactionWithUnity by subgraphWithTask<String>(
// プランで作業
tools = toolRegistry.tools,
) { input ->
"Start interacting with Unity according to the plan: $input"
}
edge(
nodeStart forwardTo nodePlanIngredients transformed {
"Create detailed plan for " + agentInput + "" +
"using the following tools: ${toolRegistry.tools.joinToString("
") {
it.name + "
description:" + it.descriptor
}}"
}
)
edge(nodePlanIngredients forwardTo interactionWithUnity onAssistantMessage { true })
edge(interactionWithUnity forwardTo nodeFinish transformed { it.result })
}
val agent = AIAgent(
promptExecutor = executor,
strategy = strategy,
agentConfig = agentConfig,
toolRegistry = toolRegistry,
installFeatures = {
install(Tracing)
install(EventHandler) {
onBeforeAgentStarted { eventContext ->
println("OnBeforeAgentStarted first (strategy: ${strategy.name})")
}
onBeforeAgentStarted { eventContext ->
println("OnBeforeAgentStarted second (strategy: ${strategy.name})")
}
onAgentFinished { eventContext ->
println(
"OnAgentFinished (agent id: ${eventContext.agentId}, result: ${eventContext.result})"
)
}
}
}
)
val result = agent.run(
" extend current opened scene for the towerdefence game. " +
"Add more placements for the towers, change the path for the enemies"
)
result
}
5) MCPプロセスをシャットダウンする
実行の最後には、必ず外部のUnity MCPサーバープロセスをクリーンアップしてください。
kotlin
// Unity MCPプロセスをシャットダウンします
process.destroy()