目录

前言

编译Python.Runtime.dll

Unity接入ChatGPT

1.第一步 准备环境

2.第二步 python代码的书写

3.第三步 C#调用python代码


前言:

相信各位游戏人都用过ChatGPT吧,那么怎么在unity里接入ChatGPT呢?本文章会通过一种极其简单的方式来实现,最终效果如下:

  1. 可以进行中文对话,可以记住一点的上下文(实际上几乎记不住任何上下文,可能是free版本的限制吧,等拿到万事达卡再试试plus版本的)
  2. 可调节的准确率(诚恳度越低准确度越高,但是更冷漠),Ai说话时的“温度”
  3. 简单的python和c#交互

好的,下面开始教程:

编译Python.Runtime.dll

看标题可知,这是基于Python.Runtime的,所以首先要拿到这个.dll文件

github地址
GitHub - pythonnet/pythonnet: Python for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers.Python for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers. - GitHub - pythonnet/pythonnet: Python for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers.https://github.com/pythonnet/pythonnet

在GitHub上clone 下来的文件需要编译成dll文件,建议使用vs进行编译,下面是教程

用vs打开解决方案(根目录下的pythonnet.sln)

在python.runtime项目上右键打开属性

  1. 将目标平台设置为x64
  2. 选择一个基路径,这个路径是你在编译好的dll文件的存放路径,是相对根目录而言的,我的就在这里面了,大家编译完成后直接在根目录里面找就好了
  3. 哦,忘记了,输出类型选择类库

然后再次右键选择生成

等待编译完成后即可在设置的基目录下看到这个dll文件

然后把这个dll文件拖到unity里

好了,准备工作已经完成,现在开始正式在Unity里接入ChatGPT!!!

Unity接入ChatGPT

首先要获取openai的api的使用权限,所以我们要有key才行

在openai的官网可以获取:key在这里弄

弄好key一定要复制好,保存好,因为一旦获取了之后,key就永久隐藏了。如果丢失了就只能再获取一次(虽然不麻烦,但是耗money呀)

ok废话介绍完毕,开始撸码,注意哦,教程是循循渐进的,代码都不是完整的,如果只想copy可以直接跳到底部复制完整代码自己看。

1.第一步 准备环境

首先引入using Python.Runtime的命名空间,设置好时间间隔,建议为20s,为啥,我也不知道,官网说的...

再就是要告诉这个插件python解释器的dll文件路径,这个很好弄,在官网上下载好python就直接能看到这个dll,还有环境变量别忘记配置了,有的大佬可能懒得登录,但是又想复制,所以我直接贴出来代码,hh

using System.IO;
using Python.Runtime;
using UnityEngine;public class PythonManager : MonoBehaviour
{// Start is called before the first frame update[SerializeField] public float _timer;private float _interval = 20;void Start(){_timer = _interval;// 获取python.all的路径(调用python解释器来执行python代码)string pythonPath = @"C:\Python311"; string dllPath = Path.Combine(pythonPath, "python311.dll");Runtime.PythonDLL = dllPath;}
}
using System.IO;
using Python.Runtime;
using UnityEngine;public class PythonManager : MonoBehaviour
{// Start is called before the first frame update[SerializeField] public float _timer;private float _interval = 20;void Start(){_timer = _interval;// 获取python.all的路径(调用python解释器来执行python代码)string pythonPath = @"C:\Python311"; string dllPath = Path.Combine(pythonPath, "python311.dll");Runtime.PythonDLL = dllPath;}
}

2.第二步 python代码的书写

这里我先说一下我的实现思路,免得大家看不懂。

我没有使用文件读取的方式来提交prompt和获取gpt回答的内容,因为我很菜,hhh,用python调用resources里的文件实在是麻烦透顶,研究了一会就放弃了,当然也可以使用绝对路径的方式来用,但是这样一打包就彻底废了,因为路径全乱了,所以干脆放弃使用文件读取的方式。然后怎么办呢???突然我想到了一个极其极其的野路子,哈哈哈哈,就是用游戏物体的名字来当临时储存“文件”,这样就方便多了,而且还不用开线程去读文件,性能也高了不少,哈哈哈哈哈快夸我。

其实呢。。。我这个文章的缺陷也很多,就是应该只能在pc上运行,我用安卓测试的时候会闪退,应该和python解释器的调用有关系,没有去研究....要是有大佬知道怎么解决的话欢迎提供解决方案哈,嘻嘻嘻嘻。

然后这是python代码的部分(纯享版,没有注释)

import UnityEngine as ue
import openai
import random
objects = ue.Object.FindObjectsOfType(ue.GameObject)
duiBaQis = []
for obj in objects:if obj.tag == 'duiBaQi':duiBaQis.append(obj)
openai.api_key = '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'
model_engine = 'gpt-3.5-turbo'
prompt = 'hello'
temperature = random.uniform(0.1,2)
for o in duiBaQis:if('@temperature:' in o.name):temperatureStr = format(temperature,'.2f')o.name = '@temperature:' + temperatureStr;
max_tokens = 255
for o in duiBaQis:if('@prompt:' in o.name):promptText = o.name.replace('@prompt:','');prompt = promptText
completion = openai.ChatCompletion.create(model='gpt-3.5-turbo',messages=[{'role': 'user', 'content': prompt}],temperature = temperature,max_tokens = max_tokens
)
print(completion.choices[0].message.content)
for o in duiBaQis:if('@ai:' in o.name):o.name = '@ai:'+ completion.choices[0].message.content;
import UnityEngine as ue
import openai
import random
objects = ue.Object.FindObjectsOfType(ue.GameObject)
duiBaQis = []#这个数组是储存所有含有duibaqi标签的游戏物体,为了加快查找速度用的,当然要是大家熟悉python的话,应该可以使用一个全局管理器来管理每一个用到的游戏物体,这样就只需要查找一遍就行了(思路就是定义几个bool值,查找完毕后设置为false,检测到false就跳过for in 循环),但是我不太会用python,hhh,没有学过...所以就放弃了,大家完全可以不比这样做
for obj in objects:if obj.tag == 'duiBaQi':duiBaQis.append(obj)#将这三个游戏物体推进这里面,哪怕是提高一丢丢的效率也是好的...
openai.api_key = '这里填在官网拿到的key'#这里是在官网得到的key
model_engine = 'gpt-3.5-turbo' #在这里选择gpt的模型,因为不同模型的使用方法有点不同,所以这里最好和我一样,等这个实现了以后大家再去琢磨别的。
prompt = 'hello'#这里是prompt,就是大家在用ChatGPT的时候给问他的那些问题
temperature = random.uniform(0.1,2)#这里就是可调节“温度”了,也就是gpt的语气
for o in duiBaQis:#查找temperature物体if('@temperature:' in o.name):temperatureStr = format(temperature,'.2f')o.name = '@temperature:' + temperatureStr;
max_tokens = 255#这个是gpt回答内容的最大字符,因为我们用的是游戏物体的名字来存储这个数据,但是在unity里游戏物体的名字最多也就能存255个字符,所以....就这样咯。
for o in duiBaQis:#查找prompt物体if('@prompt:' in o.name):promptText = o.name.replace('@prompt:','');#需要把"@prompt:"这个字符串替换掉才能作为prompt使用,不要忘记了,不然的话prompt都成啥了,笑死。prompt = promptText
#最核心的代码,调用openai提供的api,将我们设置好的model,prompt,temperature,max_tokens参数严格按照官方文档给出的格式填入,然后用completion接受返回结果。返回的是一个对象,结构比较复杂,包含很多细节,大家有兴趣可以打印出来看看,这里我们只需要使用choices[0].message.content这个数据即可。
completion = openai.ChatCompletion.create(model='gpt-3.5-turbo',messages=[{'role': 'user', 'content': prompt}],temperature = temperature,max_tokens = max_tokens
)
print(completion.choices[0].message.content)
for o in duiBaQis:#查找ai物体if('@ai:' in o.name):o.name = '@ai:'+ completion.choices[0].message.content;#直接更改ai物体的名字为gpt回答的内容,注意前缀不要忘记加上"@ai:",因为我们不是只用一次,不要卸磨杀驴了,hhh

代码讲解我都放在注释里面了,大家可以对照着代码一起看,我觉得还是蛮清晰的,哈哈。

好了,python代码的部分就是这么多,还是挺简单的,下面是用c#来调用python的部分

3.第三步 C#调用python代码

string code = @"那一坨python代码"
PythonEngine.Initialize();
using (Py.GIL())
{PythonEngine.Exec(code);
}
        string code = @"那一坨python代码"PythonEngine.Initialize();using (Py.GIL()){PythonEngine.Exec(code);}

code就是刚才写的那一坨python代码 ,注意@不要忘记写了哈,不然就没法缩进。

就这么简单?对!就这么简单,哈哈哈哈。

没了,完了,调用成功了,接入完成了,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。(博主已疯)

至于怎么gpt和游戏进行交互,怎么弄出好玩的效果,就靠各位大佬就自己发挥想象力吧~。

下面贴上我自己的代码给大家,这部分我就放在code里面了,就不贴出来凑字数了,hhh。

这是PythonManager.cs文件

using System.IO;
using Python.Runtime;
using UnityEngine;public class PythonManager : MonoBehaviour
{[SerializeField] public float _timer;private float _interval = 20;void Start(){_timer = _interval;// 获取python.all的路径(调用python解释器来执行python代码)string pythonPath = @"C:\Python311"; string dllPath = Path.Combine(pythonPath, "python311.dll");Runtime.PythonDLL = dllPath;}void Update(){_timer += Time.deltaTime;UIManager.Instance.timer.fillAmount = _timer / _interval;if (_timer < _interval) return;//控制代码执行顺序if (GameManager.Instance.canReadPy && GameManager.Instance.typeDone){ExecCode();}}public void ExecCode(){   string code = @"
import UnityEngine as ue
import openai
import random
objects = ue.Object.FindObjectsOfType(ue.GameObject)
duiBaQis = []
for obj in objects:if obj.tag == 'duiBaQi':duiBaQis.append(obj)
openai.api_key = '这里填在官网拿到的key'
model_engine = 'gpt-3.5-turbo'
prompt = 'hello'
temperature = random.uniform(0.1,2)
for o in duiBaQis:if('@temperature:' in o.name):temperatureStr = format(temperature,'.2f')o.name = '@temperature:' + temperatureStr;
max_tokens = 255
for o in duiBaQis:if('@prompt:' in o.name):promptText = o.name.replace('@prompt:','');prompt = promptText
completion = openai.ChatCompletion.create(model='gpt-3.5-turbo',messages=[{'role': 'user', 'content': prompt}],temperature = temperature,max_tokens = max_tokens
)
print(completion.choices[0].message.content)
for o in duiBaQis:if('@ai:' in o.name):o.name = '@ai:'+ completion.choices[0].message.content;
";GameManager.Instance.canReadPy = false;GameManager.Instance.typeDone = false;_timer = 0;PythonEngine.Initialize();using (Py.GIL()){PythonEngine.Exec(code);}}
}

这是DialogueManager.cs文件

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;public class DialogueManager : MonoBehaviour
{public static DialogueManager Instance;public string taDialogue;private float _timer;//缓冲时间private float _interval = 1.6f;private bool _writeDone;private string prompt;public GameObject promptObj;public GameObject aiObj;public GameObject temperatureObj;private void Awake(){Instance = this;}private void FixedUpdate(){//判断是不是点击完成了,如果点击了,就开始计时,然后执行readfile函数,放出ai的内容if (_writeDone){_timer += Time.deltaTime;if (_timer >= _interval){_writeDone = false;_timer = 0;ReadFile();}}}public void ReadFile(){//读取在temperature游戏物体的名字,来显示诚恳度,然后更改进度条。float temperature = float.Parse(temperatureObj.name.Replace("@temperature:", ""));GameManager.Instance.volume = temperature;//读取ai游戏物体的名字,来显示ai的内容string aiText = aiObj.name.Replace("@ai:", "");//哈哈哈,这里就体现我的菜了,不会正则,正能这样傻瓜式的校验if (aiText.Contains("AI") || aiText.Contains("ai") || aiText.Contains("语言模型") || aiText.Contains("开发") || aiText.Contains("人工智能")|| aiText.Contains("程序")){aiText = aiText.Replace("AI", UIManager.Instance.taName.text);aiText = aiText.Replace("ai", UIManager.Instance.taName.text);aiText = aiText.Replace("语言模型", "玩伴");aiText = aiText.Replace("开发", "培育出来");aiText = aiText.Replace("人工智能", "超级聪明");aiText = aiText.Replace("程序", "人");}taDialogue = aiText;Debug.Log("@ReadSuccess");StartCoroutine(Type(taDialogue));Debug.Log(taDialogue);}//这个函数是在玩家输入完毕以后调用的,用的是On End Edit事件,在input field这个组件里面可以看到public void Ask(string ask){prompt = ask;}//这个函数是按下准备按钮以后调用的,调用的是On Click事件,在button这个组件里可以看到public void WriteFile(){//加个判断条件,免得玩家们太多兴奋一直按个不停,导致我们的钱钱不断流失,哈哈哈,因为每次发请求都是要收费的呀!!!if (UIManager.Instance.timer.fillAmount < 0.99f){UIManager.Instance.warning.SetActive(true);return;}UIManager.Instance.taDialogue.text = UIManager.Instance.taName.text + "正在思考哦~";if (prompt == ""){prompt = "hello";}promptObj.name = "@prompt:" + prompt;//这里就是更改游戏物体的名字为我们设置好的prompt了,注意"@prompt:"不要忘记了,因为我们在python里是通过这个来查找的GameManager.Instance.canReadPy = true;GameManager.Instance.typeDone = true;_writeDone = true;Debug.Log("@WriteSuccess");}private IEnumerator Type(string str){UIManager.Instance.taDialogue.text = "";for (int i = 0; i < str.Length; i++){UIManager.Instance.taDialogue.text += str[i];yield return null;}}
}

既然都贴出来了,那就讲一下吧(其实都在注释里写上了),大家完全可以不用看的,就是我自己想写一下,hh,上面讲的那些就是核心了,这部分大家可以自己发挥创意的。

我的思路就是玩家可以输入文字(那个输入框),然后输入完以后会调用ask函数,然后把输入的内容传到prompt里,然后接着玩家点击小爪子(那个按钮)就会执行writefile函数(但是呢?还要先校验一下是不是在冷却时间里,我的ui改变都是在UIManager里完成的)

然后这是代码:

using System.Collections;
using UnityEngine;
using UnityEngine.UI;public class UIManager : MonoBehaviour
{public static UIManager Instance;public Image chenKenDu;private float _value;public Text youName;public Text taName;public Text taDialogue;public Image timer;public GameObject warning;public Text error;public bool useGpt;private void Awake(){Instance = this;_value = useGpt ? 2 : 200;}public IEnumerator ChangeValueToUI(){chenKenDu.fillAmount = 0;var filla = GameManager.Instance.volume / _value;var f = filla / 60;for (float i = 0; i < filla; i += f){yield return null;chenKenDu.fillAmount += f;}}
}

接着上面的讲,执行完WriteFile这个函数以后,就会把这三个bool值改成true,一旦为true了,PythonManager里马上就会检测到,然后执行ExceCod函数,运行python代码。这个时候_writeDone也成true了,然后开始计时,计时1.6s以后执行readfile函数,读取游戏物体的名字,然后在UI里显示出来。

至此,ChatGPT的接入就完全结束了,感谢大家能读到  3.第三步 C#调用python代码 或者能坚持读到这里,哈哈哈,那就不浪费大家时间了,就这样,结束!拜拜!

Unity接入ChatGPT基于Python.Runtime的实现相关推荐

  1. 基于python实现微信接入ChatGpt进行自动回复

    基于python实现微信接入ChatGpt进行自动回复 教程说明 下载和使用python库 如何下载python库 如何使用python库 导入python库 chatgpt部分 申请openai的k ...

  2. Python如何接入ChatGPT

    文章目录 前言 一.什么是ChatGPT? 二.下载安装步骤 1.安装Pycharm 2.安装ChatGPT 总结 前言 ChatGPT现在越来越火,许多小伙伴都不知道如何去使用,或者没有梯子/国外手 ...

  3. NLP之Chatgpt:基于openai框架通过调用API接口实现Chatgpt的吊炸天功能的图文教程(基于python代码实现)、案例应用之详细攻略

    NLP之Chatgpt:基于openai框架通过调用API接口实现Chatgpt的吊炸天功能的图文教程(基于python代码实现).案例应用之详细攻略 导读:2023年1月30日版本更新,以下是最新消 ...

  4. 基于Python+百度语音的智能语音ChatGPT聊天机器人(机器学习+深度学习+语义识别)含全部工程源码 适合个人二次开发

    目录 前言 总体设计 系统整体结构图 系统流程图 运行环境 Python 环境 Pycharm 环境 ChatterBot 环境 模块实现 1. 模型构建 2. 服务器端 3. 客户端 4. 语音录入 ...

  5. 2023最新!QQ接入ChatGpt!!!保姆级教程

    直接先上gitee!!! 基于go-cqhttp的qqbot: java实现基于cqhttp,ws连接 由于当前chatgpt热度不断,网上众多的基于chatgpt提供的api做到chat网站层出不穷 ...

  6. NVIDIA专家实战演示,教你快速搭建基于Python的车辆信息识别系统

    主讲人 | 何琨 英伟达 量子位编辑 | 公众号 QbitAI 随着智慧城市.自动驾驶的快速落地,车辆的检测和识别应用场景非常广泛,如车牌识别.车流统计.车辆属性识别等. 近日,在英伟达x量子位发起的 ...

  7. 基于python的界面自动化测试-基于Python语言的自动化测试系统的设计与实现

    黄建军+李宥谋+刘婧+周欢 摘 要: 通过分析现代工业生产对自动化测试系统的要求,提出一种基于面向对象的编程语言Python构建的自动化测试系统.利用Python语言的高效.灵活和简洁等特点,结合Py ...

  8. python量化投资必背代码-基于python的开源量化交易,量化投资架构

    原标题:基于python的开源量化交易,量化投资架构 github地址:https://github.com/bbfamily/abu abu能够帮助用户自动完善策略,主动分析策略产生的交易行为,智能 ...

  9. python毕业设计开题报告-基于Python的教学互动系统的设计与实现开题报告

    基于Python的教学互动系统的设计与实现开题报告 背景: 在各种信息技术与课堂的不断探索中,我们一直在寻找一个能提高教学效率的方式,同时可以发现要提高教学效率,在课堂教学中必不可少的就是师生间的互动 ...

最新文章

  1. SAP MM 物料主数据Plant Data Storage 1视图里的Storage Bin
  2. MethodTrace 生成的trace文件为空
  3. linux怎么复制粘贴_linux中的实用技巧和快捷键总结
  4. ansible roles角色(模块化)详解
  5. 23. which命令
  6. php 客户端上传图片,php上传图片客户端和服务器端实现方法
  7. LeetCode 434. 字符串中的单词数
  8. 深入解读 Knative Eventing 0.7 版本新特性
  9. java坦克大战源码下载
  10. Ubuntu14.04安装与卸载ROS(避坑教程)配kinetic版本安装官方网址
  11. android 内凹的圆角,css实现内凹圆角,利用圆角反向进行(转)
  12. 一加8T真机渲染图泄露:后置四摄+双闪光灯
  13. PHP 实现实时通信一般有两种方式
  14. 分发服务器linux,Linux-LVS分发服务器
  15. Solr中的q与fq参数的区别
  16. 阿里maven仓库地址
  17. 运维团队(OPS)与技术团队有效沟通配合探讨
  18. 百度Java出现:“现在学java的都是傻子”相关搜索!
  19. bouncycastle
  20. MIS和MES的区别

热门文章

  1. Python包 - networkx
  2. python Pygame的具体使用讲解
  3. Java web 图书管理系统
  4. MySQL出现Access denied for user ‘xxx‘@‘%‘ to database ‘xxxx‘问题
  5. Inception神经网络
  6. c++11之特性之std::function(书:深入应用c++11)
  7. 帝国cms cj1.php,帝国cms源码中常用函数所在位置
  8. zeromq初体验C语言版本测试程序及C++测试程序
  9. 红外线测温仪方案开发
  10. 机器学习模型训练测试完整步骤