1. Unity 里第一次跑通大模型对话卡在哪一步很多 Unity 开发者想给项目加个 AI 功能第一反应是去各家大模型官网注册、拿 Key、翻文档然后发现每个平台的请求地址、鉴权方式、模型名都不一样。今天接 DeepSeek明天想换 Qwen 或者 Claude代码里到处是硬编码的 URL 和 Key改起来烦得很。这篇面向的是第一次在 Unity 里接入大模型 API 的开发者目标很明确从零跑通一次对话请求拿到模型返回的文本显示在 UI 上。核心检索词就三个——AI大模型、API、Unity外加 DeepSeek 和统一 Key 的管理思路。我试过直接在每个脚本里写死不同平台的 Key项目稍微大一点就乱套。后来改成用 TaoToken 做统一入口一个 Key 对应多个模型Unity 侧只维护一份配置切换模型只改一个 Model ID 字符串。下面把完整链路拆开讲先拿 Key 和 Base URL再写 C# 请求脚本最后用一次真实请求验证返回结果。适合谁看有 Unity 基础、写过协程和 UnityWebRequest、但没接过大模型 API 的开发者。不需要你会 Python也不需要你懂 Transformer 原理只要能发 HTTP 请求就行。整个流程分四步配置统一 Key → 写请求数据结构 → 写 UnityWebRequest 协程 → 发一次请求看返回。每一步都有可复制的代码和参数照着做就能跑通。2. TaoToken 统一 Key 的前置准备与 Base URL 配置在写 Unity 代码之前先把「钥匙」和「门牌号」准备好。大模型 API 的调用本质就是向一个 HTTP 端点 POST 一段 JSON端点地址就是 Base URL身份凭证就是 API Key。TaoToken 的作用是把多个模型的调用收敛到一个入口。你不需要为 DeepSeek 记一个地址、为 Qwen 记另一个地址统一用同一个 Base URL通过 Model ID 区分要调哪个模型。这对 Unity 项目特别友好——配置结构体里只留 url、model、apiKey 三个字段换模型只动 model。先到官网了解整体能力地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注册登录后进入控制台准备创建 Key。创建 Key 的入口在 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。点创建填个名字比如 unity-demo生成的 Key 只显示一次复制下来存好。这个 Key 就是后面 C# 脚本里 Authorization 头要用的东西。Base URL 用 https://taotoken.net/api 注意这个地址后面不加 UTM 参数直接作为请求前缀。完整的对话端点是在它后面拼 /v1/chat/completions也就是最终 POST 的地址是 https://taotoken.net/api/v1/chat/completions 。这一点和 OpenAI 兼容格式一致Unity 侧不用做特殊适配。Model ID 这块DeepSeek 常用的是 deepseek-chat对应 V3和 deepseek-reasoner对应 R1。你在 TaoToken 控制台的模型列表里能看到当前可用的模型名直接复制那个字符串填到代码里。如果之后想换成别的模型只改这个字符串URL 和 Key 都不动。注意Key 属于敏感凭证不要提交到 Git 仓库也不要写死在会打包分发的客户端里。原型阶段可以放本地配置正式项目建议走服务端转发。配置信息整理成一张表方便对照配置项值说明Base URLhttps://taotoken.net/api统一入口前缀对话端点/v1/chat/completions拼在 Base URL 后API Key控制台创建只显示一次妥善保存Model IDdeepseek-chat可替换为其他模型名鉴权头Authorization: Bearer标准 Bearer 格式内容类型Content-Type: application/json固定如果你还想在写代码前先在线验证一下模型能不能通可以用模型对话页面直接发一条消息试试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。这一步能排除掉 Key 本身的问题省得后面在 Unity 里排查半天发现是 Key 没生效。前置准备就这些接下来进 Unity 写代码。3. Unity C# 请求脚本与 DeepSeek 模型参数配置这一节是核心把可复制的配置和脚本都给全。Unity 侧我用的是 UnityWebRequest 协程JSON 序列化用 Newtonsoft.JsonUnity 里通过 Package Manager 装 com.unity.nuget.newtonsoft-json。先定义请求和响应的数据结构。大模型 API 的消息格式基本统一都是 model messages 数组messages 里每条有 role 和 content。using System; [Serializable] public class AIMessage { public string model; public Message[] messages; public bool stream false; [Serializable] public class Message { public string role; public string content; } } [Serializable] public class AIResponse { public Choice[] choices; [Serializable] public class Choice { public Message message; } [Serializable] public class Message { public string content; } }再定义一个配置结构体把 url、model、apiKey 三个字段收在一起方便切换模型。这里 url 直接填完整的对话端点。[Serializable] public struct AIConfig { public string url; public string model; public string apiKey; public AIConfig(string url, string model, string apiKey) { this.url url; this.model model; this.apiKey apiKey; } }实际使用时这样初始化把前面拿到的信息填进去AIConfig deepSeekConfig new AIConfig( https://taotoken.net/api/v1/chat/completions, deepseek-chat, 你的APIKey );然后是发送请求的协程。用 UnityWebRequestPOST 方法uploadHandler 装 JSON 字节downloadHandler 收返回文本两个 Header 分别设 Content-Type 和 Authorization。using System.Collections; using System.Text; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Networking; public class AIClient : MonoBehaviour { public AIConfig usingModel; public IEnumerator SendMessageToAIModel(string message, System.Actionstring callback) { AIMessage msg new AIMessage { model usingModel.model, messages new AIMessage.Message[] { new AIMessage.Message { role user, content message } } }; string json JsonConvert.SerializeObject(msg); UnityWebRequest request new UnityWebRequest(usingModel.url, POST); request.uploadHandler new UploadHandlerRaw(Encoding.UTF8.GetBytes(json)); request.downloadHandler new DownloadHandlerBuffer(); request.SetRequestHeader(Content-Type, application/json); request.SetRequestHeader(Authorization, Bearer usingModel.apiKey); yield return request.SendWebRequest(); if (request.result UnityWebRequest.Result.Success) { AIResponse response JsonConvert.DeserializeObjectAIResponse(request.downloadHandler.text); callback?.Invoke(response.choices[0].message.content); } else { Debug.LogError(请求失败: request.error); Debug.LogError(返回内容: request.downloadHandler.text); callback?.Invoke(FAILED); } } }几个参数说明一下。stream 设成 false 表示非流式一次性拿到完整回复原型阶段够用也最好调试。如果要做打字机效果把 stream 改成 true然后逐行解析 SSE 数据那是另一个话题这篇先不展开。model 字段就是前面说的 Model IDdeepseek-chat 对应 V3。如果你想试 deepseek-reasoner直接换这个字符串就行URL 和 Key 都不用动这就是统一入口的好处。提示Newtonsoft.Json 在 Unity 里需要手动装包Package Manager 里搜 Newtonsoft 或者改 manifest.json 加 com.unity.nuget.newtonsoft-json。别用 Unity 自带的 JsonUtility它处理嵌套数组和可选字段很别扭。脚本挂到场景里任意 GameObject 上在 Inspector 里把 usingModel 填好或者用代码初始化。接下来写个调用入口把用户输入传进去回调里更新 UI。4. 发一次真实请求验证返回结果代码写完了得跑一次看结果。在场景里建一个 InputField 做输入、一个 Button 触发、一个 Text 显示回复。Button 的 onClick 绑一个方法里面启动协程。public class ChatController : MonoBehaviour { public AIClient client; public InputField inputField; public Text resultText; public void OnSendClick() { string userInput inputField.text; if (string.IsNullOrEmpty(userInput)) return; resultText.text 思考中...; StartCoroutine(client.SendMessageToAIModel(userInput, OnReply)); } private void OnReply(string reply) { resultText.text reply; } }把 AIClient 和 ChatController 挂好引用拖上运行。输入一句「用一句话解释什么是协程」点发送。正常的话几秒内 Text 上会出现类似这样的返回协程是一种可以在多个帧之间暂停和恢复执行的函数常用于处理需要等待的操作比如网络请求或延时逻辑。这就是一次完整的对话请求跑通了。请求体长这样{ model: deepseek-chat, messages: [ { role: user, content: 用一句话解释什么是协程 } ], stream: false }返回体结构是 choices 数组取 choices[0].message.content 就是模型回复的文本。如果返回里带了 usage 字段能看到这次消耗的 token 数输入和输出分别计费。想验证模型切换把 usingModel 的 model 改成 deepseek-reasoner 再发一次返回内容风格会不一样推理类模型会先输出思考过程再给结论。URL 和 Key 完全没动这就是统一 Key 的价值。如果你在 Unity 里不方便先跑也可以先在模型对话页面发同样的消息对比返回格式是否一致https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。两边格式一致说明 Unity 侧的 JSON 拼装没问题。实测下来非流式请求在正常网络下 2 到 5 秒能返回取决于模型和回复长度。原型阶段这个延迟可以接受正式项目如果要求实时感再考虑流式。5. 常见报错排查401、local proxy failed 与 reading choices第一次接很容易踩几个坑这里按真实报错对照排查。401 Unauthorized。返回体里通常是 {error:{message:Invalid API key}} 之类。原因就三个Key 复制时带了空格、Key 已删除或过期、Authorization 头格式写错。检查 request.SetRequestHeader(Authorization, Bearer apiKey) 里 Bearer 后面有一个空格Key 本身没有换行。如果 Key 是在控制台刚创建的确认复制完整了只显示一次的那种。local proxy failed / Connection error。Unity 控制台报 UnityWebRequest result 是 ConnectionError或者提示无法连接。先确认 Base URL 拼对了是 https://taotoken.net/api/v1/chat/completions 不要漏掉 /v1 或者多写斜杠。再确认本机网络能正常访问外网 HTTPS公司内网如果有防火墙策略可能需要放行。这个报错和 Key 无关纯粹是网络层没通。reading choices 时 NullReferenceException。代码跑到 response.choices[0] 就崩了。说明返回的 JSON 里没有 choices 字段通常是请求失败但走了 Success 分支或者返回结构和你定义的不一致。排查方法在反序列化之前先把 request.downloadHandler.text 打出来看。常见情况是返回了 error 对象比如模型名写错、参数不合法。把原始返回打出来问题一目了然。模型名不存在 / model not found。Model ID 拼错了比如把 deepseek-chat 写成 deepseek_chat 或者 DeepSeek-Chat。大小写和连字符都要和控制台里显示的一致直接复制最稳。OAuth 相关报错。如果你看到 OAuth 字样通常是把鉴权方式搞混了。对话 API 用的是 Bearer Token不是 OAuth 流程。确认你用的是 API Key 而不是别的凭证Header 就是 Authorization: Bearer 没有额外步骤。排查顺序建议先看 request.result 是不是 Success不是就先解决网络和鉴权是 Success 但解析崩就把原始 text 打出来看结构。90% 的问题在原始返回里能直接看出来。注意调试阶段把 Debug.LogError 的返回内容打全别只打 request.error那个信息量不够。另外如果你用的是 Cline MCP 或者 Claude Code 这类工具做辅助开发配置里同样需要 Base URL、Key、Model ID 三件套格式和 Unity 侧一致只是配置文件位置不同。Unity 这边就是代码里的 AIConfig工具那边是各自的 settings 文件本质一样。6. 从原型到可用Unity AI 功能的下一步跑通一次对话只是起点。真正要把 AI 功能做进项目还有几件事值得提前想。第一是 Key 的安全。原型阶段放本地没问题但如果要打包发布客户端里的 Key 等于公开的。正确做法是 Unity 请求你自己的服务端由服务端持有 Key 再去调大模型。这样 Key 不落地到用户设备也能在服务端做限流和内容过滤。第二是上下文管理。现在每次请求只发一条 user 消息模型没有记忆。要做多轮对话得把历史消息按 role 顺序拼进 messages 数组user 和 assistant 交替。注意 token 消耗会随历史增长长对话要截断或者做摘要。第三是流式输出。非流式要等全部生成完才显示体验上差一截。改成 stream: true 后返回是 SSE 格式每行 data: 开头需要逐块解析并追加到 UI。Unity 里可以用 DownloadHandlerScript 做增量处理这块代码量比非流式多一些但打字机效果值得。第四是模型选择策略。简单问答用便宜的模型复杂推理用 reasoner代码生成用专门的 coding 模型。TaoToken 统一入口的好处在这里体现——切换只改 Model ID不用改请求逻辑。如果你要长期做编码类 Agent可以了解下 Coding Plan 的用法https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入文档里有各端点的详细参数说明遇到字段不确定的时候查这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。API Keys 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 需要新建或轮换 Key 的时候用。最后给个实用建议把 AIConfig 做成 ScriptableObject在 Editor 里可视化配置多个模型运行时按需切换。这样策划也能自己改模型名做测试不用每次找你改代码。原型跑通之后先把配置抽出来后面扩展会顺很多。