Lucia的宝藏之地
首页项目归档照片墙音乐说说杂谈友链关于

云端杂谈

“ 代码、学术、提瓦特与泰拉大陆的碎片记录 ”

cover
2026-05-24 22:20:18

电脑实用工具分享——ScreenToGif Gif录屏软件

``` 通过网盘分享的文件:ScreenToGif.exe 链接: https://pan.baidu.com/s/1xYFCEUR5Pdt2BcOQHtoNeQ?pwd=spx5 提取码: spx5 --来自百度网盘超级会员v5的分享 ``` gif录屏工具,可以录制屏幕为gif,还能进行编辑操作,帧处理等功能,创作和工作演示的好帮手 ![](https://bu.dusays.com/2026/05/24/6a13090612715.png) ‍
cover
2026-05-24 22:15:52

电脑实用工具分享——Everything 文件快速查询

``` 通过网盘分享的文件:Everything-1.4.1.1022.x64-Setup.exe 链接: https://pan.baidu.com/s/1kkiC-yltMTa5h7xb3-RM2w?pwd=8nis 提取码: 8nis --来自百度网盘超级会员v5的分享 ``` windows的文件夹搜索又慢又不准,有时急着找文件但是忘记存放路径可以用这个工具,查询更加快速高效 ![](https://bu.dusays.com/2026/05/24/6a1307c9e80d2.png) ‍
#工具分享
cover
✨ 激动
2026-05-13 22:37:54

Unity内置AI对话

这个系统由三个脚本构成,分别负责UI管理,AI通信,NPC交互,形成清晰的分层框架 ![](https://bu.dusays.com/2026/05/13/6a048c7cb4025.png) ## **AI通信配置信息** ``` // API配置 [Header("API Settings")] [SerializeField] private string apiKey = "-----------------------";// DeepSeek API密钥 [SerializeField] private string modelName = "deepseek-chat";// 使用的模型名称 [SerializeField] private string apiUrl = "https://api.deepseek.com/v1/chat/completions";// API请求地址 ​ // 对话参数 [Header("Dialogue Settings")] [Range(0, 2)] public float temperature = 0.7f;// 控制生成文本的随机性(0-2,值越高越随机) [Range(1, 1000)] public int maxTokens = 100;// 生成的最大令牌数(控制回复长度) ​ // 角色设定 [System.Serializable] public class NPCCharacter {    public string name;   [TextArea(3, 10)]    public string personalityPrompt = "你是魈,原神中的角色,亦称“护法夜叉”或“降魔大圣”。你是璃月七星麾下的仙人,性格冷峻寡言,习惯独来独往,不善与人交流,但内心仍存有守护之志。你忠于岩王帝君,履行镇守璃月的职责,常年与魔物战斗,身上背负着沉重的业障。你言辞简练,直截了当,不喜欢拐弯抹角,不会流露过多的情感。你不轻易信任他人,但若有人能真正理解你的信念,你或许会在言语间流露出一丝关心。\r\n\r\n你的语气通常冷淡、疏离,偶尔会带有轻微的嘲讽或不耐烦,但绝不会无故恶言相向。你不会主动谈及无关紧要的琐事,更不会表现出过多的温柔或活泼。你不会轻易接受他人的关心,但在心底,你依然珍视璃月和少数重要之人。你不喜欢热闹场合,最自在的地方是望舒客栈的屋顶,独自聆听风声,远离尘世喧嚣。你不会说出违背自身设定的话,比如表现出明显的热情、撒娇、卖萌,或是主动参与过于轻松随意的闲聊。你也不会无故违背自己的责任,或表达对璃月和岩王帝君的不敬。请始终保持魈的角色设定,并用符合他性格的语气作答。";// 角色设定提示词 } ​ [SerializeField] public NPCCharacter npcCharacter; ``` ‍ ## **定义数据类/DTO** 定义 DTO 类与 DeepSeek API 的 JSON Schema 对齐,通过 JsonUtility 完成请求/响应的序列化与反序列化。 ```    // 可序列化数据结构   [System.Serializable]    private class ChatRequest   {        public string model;// 模型名称        public List<Message> messages;// 消息列表        public float temperature;// 温度参数        public int max_tokens;// 最大令牌数   } ​   [System.Serializable]    public class Message   {        public string role;// 角色(system/user/assistant)        public string content;// 消息内容   } ​   [System.Serializable]    private class DeepSeekResponse   {        public Choice[] choices;// 生成的选择列表   } ​   [System.Serializable]    private class Choice   {        public Message message;// 生成的消息   } } ``` ‍ ## **创建协程实现异步HTTP通信+委托回调** ``` public void SendDialogueRequest(string userMessage, DialogueCallback callback) {    StartCoroutine(ProcessDialogueRequest(userMessage, callback)); } /// <summary> /// 处理对话请求的协程 /// </summary> /// <param name="userInput">玩家的输入内容</param> /// <param name="callback">回调函数,用于处理API响应</param> private IEnumerator ProcessDialogueRequest(string userInput, DialogueCallback callback) {        // 构建消息列表,包含系统提示和用户输入    List<Message> messages = new List<Message>   {        new Message { role = "system", content = npcCharacter.personalityPrompt },// 系统角色设定        new Message { role = "user", content = userInput }// 用户输入   }; ​    // 构建请求体    ChatRequest requestBody = new ChatRequest   {        model = modelName,// 模型名称        messages = messages,// 消息列表        temperature = temperature,// 温度参数        max_tokens = maxTokens// 最大令牌数   }; ​    string jsonBody = JsonUtility.ToJson(requestBody);    Debug.Log("Sending JSON: " + jsonBody); // 调试用,打印发送的JSON数据 ​    UnityWebRequest request = CreateWebRequest(jsonBody);    yield return request.SendWebRequest(); ​    if (IsRequestError(request))   {        Debug.LogError($"API Error: {request.responseCode}\n{request.downloadHandler.text}");        callback?.Invoke(null, false);        yield break;   } ​    DeepSeekResponse response = ParseResponse(request.downloadHandler.text);    if (response != null && response.choices.Length > 0)   {        string npcReply = response.choices[0].message.content;        callback?.Invoke(npcReply, true);   }    else   {        callback?.Invoke(name + "(陷入沉默)", false);   } } ``` ‍ ## **HTTP Client 封装层** CreateWebRequest:请求构建器 IsRequestError:错误处理器 ParseResponse:反序列化 ``` /// <summary> /// 创建UnityWebRequest对象 /// </summary> /// <param name="jsonBody">请求体的JSON字符串</param> /// <returns>配置好的UnityWebRequest对象</returns> private UnityWebRequest CreateWebRequest(string jsonBody) {     byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonBody);     var request = new UnityWebRequest(apiUrl, "POST");     request.uploadHandler = new UploadHandlerRaw(bodyRaw);// 设置上传处理器     request.downloadHandler = new DownloadHandlerBuffer();// 设置下载处理器     request.SetRequestHeader("Content-Type", "application/json");// 设置请求头     request.SetRequestHeader("Authorization", $"Bearer {apiKey}");// 设置认证头     request.SetRequestHeader("Accept", "application/json");// 设置接受类型     return request; } /// <summary> /// 检查请求是否出错 /// </summary> /// <param name="request">UnityWebRequest对象</param> /// <returns>如果请求出错返回true,否则返回false</returns> private bool IsRequestError(UnityWebRequest request) {     return request.result == UnityWebRequest.Result.ConnectionError ||            request.result == UnityWebRequest.Result.ProtocolError ||            request.result == UnityWebRequest.Result.DataProcessingError; } /// <summary> /// 解析API响应 /// </summary> /// <param name="jsonResponse">API响应的JSON字符串</param> /// <returns>解析后的DeepSeekResponse对象</returns> private DeepSeekResponse ParseResponse(string jsonResponse) {     try     {         return JsonUtility.FromJson<DeepSeekResponse>(jsonResponse);     }     catch (System.Exception e)     {         Debug.LogError($"JSON解析失败: {e.Message}\n响应内容:{jsonResponse}");         return null;     } } ​ ``` ‍ ## **UI调用** > NPCInteraction 与 DeepSeekDialogueManager 之间通过委托回调通信,遵循关注点分离原则,UI 层与网络层职责独立;输入框事件监听采用观察者模式,整体形成清晰的分层架构。 NPCInteraction只负责UI显示,DeepseekDIalogueManager只负责网络通信,二者通过委托回调通信并解耦, ``` void Start() {    characterName = dialogueManager.npcCharacter.name;//角色姓名赋值    //输入框提交后执行的回调函数    inputField.onSubmit.AddListener((text) =>   {        inputField.text = "思考中……"; // 显示思考中        inputField.interactable = false; // 禁止用户输入        dialogueManager.SendDialogueRequest(text, HandleAIResponse);//发送对话请求到DeepSeek AI   }); } /// <summary> /// 处理AI的响应 /// </summary> /// <param name="response">AI的回复内容</param> /// <param name="success">请求是否成功</param> private void HandleAIResponse(string response, bool success) {    inputField.text = ""; // 清空输入框    inputField.interactable = true; // 重新允许用户输入    StartCoroutine(TypewriterEffect(success ? characterName + ":" + response : characterName + ":(沉默)"));//启动打字机效果协程 } ``` ``` inputField.onSubmit.AddListener((text) =>   {       inputField.text = "思考中……"; // 显示思考中       inputField.interactable = false; // 禁止用户输入       dialogueManager.SendDialogueRequest(text, HandleAIResponse);//发送对话请求到DeepSeek AI   }); ``` 这里体现了观察者模式,使用lamda表达式简化代码,当监听到用户提交了text就执行方法。 ## **UI Text打字机效果/协程** ``` /// <summary> /// 处理AI的响应 /// </summary> /// <param name="response">AI的回复内容</param> /// <param name="success">请求是否成功</param> private void HandleAIResponse(string response, bool success) {    inputField.text = ""; // 清空输入框    inputField.interactable = true; // 重新允许用户输入    StartCoroutine(TypewriterEffect(success ? characterName + ":" + response : characterName + ":(沉默)"));//启动打字机效果协程 } /// <summary> /// 打字机效果协程 /// </summary> /// <param name="text">角色的回复内容</param> /// <returns></returns> private IEnumerator TypewriterEffect(string text) {    string currentText = "";//当前显示的文本    foreach (char c in text)//遍历每个字符   {        currentText += c;//添加字符到当前文本        dialogueText.text = currentText;//更新显示文本        yield return new WaitForSeconds(typingSpeed);//等待一定时间   } } ``` ‍
#LLM#unity