Unity集成GPT

Posted 辛羊华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity集成GPT相关的知识,希望对你有一定的参考价值。

GPT想必是最近互联网最火的话题了,作为一个Unity开发者,今天来介绍一下如何在Unity中使用GPT。

一、API 密钥

使用GPT的API首先要获得密钥,如下进入OpenAI官网(https://platform.openai.com/account/api-keys)–>选择自己的账号–>查看API密钥,然后创建一个自己的密钥(创建的后要记得复制好密钥)。

二、GPT模型

进入OpenAI文档(https://platform.openai.com/docs/models)页面可以看到目前主要可以使用的AI模型,如下从GPT3.0到GPT4.0。

目前可以免费使用的最高版本就是GPT-3.5,所以这里主要来介绍一下如何集成 gpt-3.5-turbo。

三、gpt-3.5-turbo 集成

进入API文档(https://platform.openai.com/docs/api-reference/chat/create)选择Chat,就是gpt-3.5-turbo的使用文档。
OpenAI的接口访问主要都是使用Post请求,这里gpt-3.5-turbo的Post地址是:

https://api.openai.com/v1/chat/completions

请求与回调内容都是Json。
发送请求格式Request:


  "model": "gpt-3.5-turbo",
  "messages": ["role": "user", "content": "Hello!"]

回调相应格式Respond:


  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "choices": [
    "index": 0,
    "message": 
      "role": "assistant",
      "content": "\\n\\nHello there, how may I assist you today?",
    ,
    "finish_reason": "stop"
  ],
  "usage": 
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  

在Unity中则可以直接使用UnityWebRequest来实现Post请求:

UnityWebRequest request = new UnityWebRequest(m_ApiUrl, "POST")

m_ApiUrl就是前面的Post地址。
在发送的信息中"model"就是使用示例中的"gpt-3.5-turbo",这是最新的可以免费使用的AI模型。
发送的消息"messages"中每个message都包含一个"role"(角色)和一个"content"(角色对于的内容)。
"role"可以选择 “system”, “user”, 或 “assistant”:

  • "system"一般作为角色设定,比如NPC扮演的话可以设定NPC的身份、特点等;
  • "user"就是用户角色;
  • "assistant"就是AI的角色身份。
    这里可能会好奇,为什么我们向GPT请求要发送AI角色的内容,其实这里我们主要是把上一次的提问和AI的回答都传回去,这样GPT就相当于有了记忆,知道我们前面对话说了啥,因此对话就不会是一个个孤立的问答了,官方的ChatGPT聊天同样是使用了这个原理。
    这里给上完整的gpt-3.5-turbo示例请求代码
public class GptTurboScript : MonoBehaviour

    /// <summary>
    /// api地址
    /// </summary>
    public string m_ApiUrl = "https://api.openai.com/v1/chat/completions";
    /// <summary>
    /// gpt-3.5-turbo
    /// </summary>
    public string m_gptModel = "gpt-3.5-turbo";
    /// <summary>
    /// 缓存对话
    /// </summary>
    [SerializeField]public List<SendData> m_DataList = new List<SendData>();
    /// <summary>
    /// AI人设
    /// </summary>
    public string Prompt;

    private void Start()
    
        //运行时,添加人设
        m_DataList.Add(new SendData("system", Prompt));
    

    public 

    /// <summary>
    /// 调用接口
    /// </summary>
    /// <param name="_postWord">发送的消息</param>
    /// <param name="_openAI_Key">密钥</param>
    /// <param name="_callback">GPT的回调</param>
    /// <returns></returns>
     IEnumerator GetPostData(string _postWord,string _openAI_Key, System.Action<string> _callback)
    
        //缓存发送的信息列表
        m_DataList.Add(new SendData("user", _postWord));

        using (UnityWebRequest request = new UnityWebRequest(m_ApiUrl, "POST"))
        
            PostData _postData = new PostData
            
                model = m_gptModel,
                messages = m_DataList
            ;

            string _jsonText = JsonUtility.ToJson(_postData);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(_jsonText);
            request.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);
            request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();

            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Authorization", string.Format("Bearer 0", _openAI_Key));

            yield return request.SendWebRequest();

            if (request.responseCode == 200)
            
                string _msg = request.downloadHandler.text;
                MessageBack _textback = JsonUtility.FromJson<MessageBack>(_msg);
                if (_textback != null && _textback.choices.Count > 0)
                

                    string _backMsg = _textback.choices[0].message.content;
                    //添加记录
                    m_DataList.Add(new SendData("assistant", _backMsg));
                    _callback(_backMsg);
                
            
        
    

    #region 数据包

    [Serializable]public class PostData
    
        public string model;
        public List<SendData> messages;
    

    [Serializable]
    public class SendData
    
        public string role;
        public string content;
        public SendData()  
        public SendData(string _role,string _content) 
            role = _role;
            content = _content;
        

    
    [Serializable]
    public class MessageBack
    
        public string id;
        public string created;
        public string model;
        public List<MessageBody> choices;
    
    [Serializable]
    public class MessageBody
    
        public Message message;
        public string finish_reason;
        public string index;
    
    [Serializable]
    public class Message
    
        public string role;
        public string content;
    

    #endregion

使用只需要调用GetPostData这个方法,传入你要发送的消息和你的API密钥,然后在_callback回调中获取到GPT返回的信息就可以了。

四、GPT绘画

和gpt-3.5-turbo类似,画图的Post接口为:

https://api.openai.com/v1/images/generations

发送请求格式Request:


  "prompt": "A cute baby sea otter",
  "n": 2,
  "size": "1024x1024"

"prompt"为要绘制的图片描述;"n"为绘制数量;"size"为图片大小。
回调相应格式Respond:


  "created": 1589478378,
  "data": [
    
      "url": "https://..."
    ,
    
      "url": "https://..."
    
  ]

返回的"url"就是图片的路径地址。
同样赋上完整的请求代码:

public class GPTImage : MonoBehaviour

    //API key
    [SerializeField] private string m_OpenAI_Key = "填写你的Key";
    /// <summary>
    /// api地址
    /// </summary>
    public const string m_ApiUrl = "https://api.openai.com/v1/images/generations";
    /// <summary>
    /// 调用接口
    /// </summary>
    /// <param name="_postWord"></param>
    /// <param name="_openAI_Key"></param>
    /// <param name="_callback"></param>
    /// <returns></returns>
    public IEnumerator GetPostData(string _postWord, Action<List<string>> _callback)
    

        using (UnityWebRequest request = new UnityWebRequest(m_ApiUrl, "POST"))
        
            PostData _postData = new PostData(_postWord, 10, "512x512");

            string _jsonText = JsonUtility.ToJson(_postData);
            byte[] data = System.Text.Encoding.UTF8.GetBytes(_jsonText);
            request.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);
            request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();

            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Authorization", string.Format("Bearer 0", m_OpenAI_Key));

            yield return request.SendWebRequest();

            if (request.responseCode == 200)
            
                string _msg = request.downloadHandler.text;
                MessageBack _textback = JsonUtility.FromJson<MessageBack>(_msg);
                if (_textback != null && _textback.data.Count > 0)
                

                    List<string> urlList= new List<string>();
                    for (int i = 0; i < _textback.data.Count; i++)
                    
                        Debug.Log(_textback.data[i].url);   //图片路径
                        urlList.Add(_textback.data[i].url);
                    
                    _callback(urlList);
                
            
        
    

    #region 数据包
    [Serializable]
    public class PostData
    
        public string prompt;
        public int n;
        public string size;

        public PostData(string _prompt, int _n, string _size)
        
            prompt = _prompt;
            n = _n;
            size = _size;
        
    
    [Serializable]
    public class MessageBack
    
        public string created;
        public List<Data> data;
    
    [Serializable]
    public class Data
    
        public string url;
    

    #endregion

五、AICommand

AICommand是一位日本的开发者keijiro通过使用gpt-3.5-turbo来实现命令操控Unity,比如输入:创建物体、创建灯光、添加组件、改变颜色等。但这些命令使用英语才比较准确,通过下载源码(https://github.com/keijiro/AICommand)研究后,把发送给GPT的前置提示改成中文后就能比较好的识别中文命令了。

    static string WrapPrompt(string input)
      => "Write a Unity Editor script.\\n" +
         " - It provides its functionality as a menu item placed \\"Edit\\" > \\"Do Task\\".\\n" +
         " - It doesn’t provide any editor window. It immediately does the task when the menu item is invoked.\\n" +
         " - Don’t use GameObject.FindGameObjectsWithTag.\\n" +
         " - There is no selected object. Find game objects manually.\\n" +
         " - I only need the script body. Don’t add any explanation.\\n" +
         "The task is described as follows:\\n" + input;

如上,"input"为我们要输入的命令,前面部分为对命令的一些解释要求,其主要逻辑是让GPT先生成一个Editor模式下运行的脚本,脚本里面来实现我们描述的功能,比如“创建10个立方体”,当执行完这个脚本的功能后再把脚本删除,这样在感观上就像GPT能在Unity做一些操作。
在使用过程中遇到一些问题:
1.GPT给的脚本中时常给你一些使用提示,而我们需要的是存脚本才能正常运行,所以就需要在前置描述里面特别强调我们只需要纯代码文本。
2.因描述不准确、理解偏差或功能复杂等情况导致GPT生成的脚本并不能正常运行,其实这个目前并不好解决,AICommand能实现的也是一些简单基础的操作,但可以通过一些人为的操作,让GPT半自动的来实现一些更复杂的工作,比如可以让GPT在Unity生成脚本后我们在去挂载或修改脚本,这样加上人的操作虽然感觉不是那么智能,但也能提高很多效率。目前Unity商店中就有人做了一款类似的插件。

六、总结

目前GPT在Unity的应用虽还不能很高的智能化,但可以使用他生产代码、修改代码、以及给出一些优化、设计建议等,从而很大程度的提升我们的工作效率。

Unity集成华为游戏服务SDK方式:集成Unity官方游戏SDK

Unity官方为广大游戏开发者提供了集成华为HMS SDK的方式,包含游戏和华为hms core其他功能模块,这里只介绍如何集成游戏模块。

Unity官方文档链接:​https://docs.unity.cn/cn/Packages-cn/com.unity.huaweiservice@1.3/manual/gameservices_cn.html

打开文档后,左上角可以查看文档版本,默认是1.3.4版本。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译

当前最新文档是2.3.0,建议切换到最新版本集成sdk,具体接口在1.3.4版本,接入接口时需要切换回1.3.4版本。点击左上角下三角符号切换:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_02

如果集成过程中遇到问题,可以登录网页版unity账号,点击右上角中问号,咨询unity官方技术人员。附上unity链接:https://distribute.dashboard.unity.com/list

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_03

先下载华为游戏unity demo,下载链接:

https://github.com/Unity-Technologies/HuaweiServiceSample

使用的unity版本2020.2.4.f1c1,下面言归正传,集成步骤如下:

下载后将demo导入到unityhub,在unityHub中打开demo,在弹出的弹窗中选择ignore,如图:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_04

等待项目导入project到unity。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_05

导入之后,点击file->build settings->player settings,将产品信息替换为自己的。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_06

对应的将包名和版本号替换为自己的。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_07

将自己在AGC后台配置应用的agconnect-services.json文件放在如下目录下。

Json文件获取地址参考文档:

https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/integrate-as-sdk-0000001050435953

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_08

将以下红线选中文件删掉:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_09

重新创建自己应用的gradle文件,创建方法为在player setting页面,将以下选项打勾,unity自动在对应位置创建文件,如图:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_10

然后在对应的文件里面加入Game Service SDK的配置,我们参考unity官网提供的文档如下章节完成相关配置,不做赘述。

链接:

https://docs.unity.cn/cn/Packages-cn/com.unity.hms@1.2/manual/appgalleryChinese.html#1-%E4%BB%8Eunity-asset-store%E5%AF%BC%E5%85%A5%E6%AD%A4%E5%8D%8E%E4%B8%BAhms-core-app-services-sdk

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_11

配置完后,选中game的unity文件编译

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_12

出现弹窗

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_13

这是要签名的意思,默认勾选了签名,改为不勾选可以先跳过签名

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_14

但是最终发布还是需要签名,我这里直接配置签名文件

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_15

选中我本地的keystore文件,必须是keystore文件,jks文件识别不到,自己本地转化一下即可。

这里顺便写一下我自己的转化步骤:

1. 先将jks转化为中间文件.p12,命令行输入 :

keytool -importkeystore –srckeystore  后缀为jks文件的路径 -deststoretype PKCS12 -destkeystore  p12的存放路径

2. 将.p12转化为keystore文件,命令行输入:

keytool -v -importkeystore –srckeystore  p12文件的路径 -srcstoretype PKCS12 –destkeystore  keystore存放路径 -deststoretype JKS

将keystore文件导入后输入自己的签名文件的密码。如图

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_16

重新编译,然后在控制台报错:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_17

看这个意思应该是c#文件里面的错误,模块太多,我只需要游戏相关的就行,咨询了unity人员说可以把不相关的删掉,还帮我划分了下可以删除的部分。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_18

按照图片删掉里面框住的部分,再编译,报错如下:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_19

看到里面报错很多刚刚删除的模块相关文件找不到,找到这个test文件夹,删掉,还有这个错误

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_20

也将对应路径下的void文件删掉,重新build。然后报错

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_21

看这个报错cs文件有错,看了代码没发现错误,重启unity编辑器或者操作一个简单粗暴的方法,创建新项目,然后把assets文件夹挪进去,重新编译,这样可以避免因为一些环境不同的原因出现一些无从下手的问题。我这里重启后之前错误消失,出现了其他报错。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_22

看样子全部是ui文件夹里面的报错,应该是用到了之前删除的文件,从而找不到了。把ui文件夹删掉,重新build,报错:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_23

提示我包不存在,应该是哪里有用到,最后我在这个路径下找到相关文件夹

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_集成SDK_24

删掉后重新build,编译成功,成功打包apk。

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_重新编译_25

手机安装后效果如图:

Unity集成华为游戏服务SDK方式(一):集成Unity官方游戏SDK_html_26

安装后就可以自行调测接口啦。

unity接口和华为原生游戏sdk接口映射可以参考:

https://developer.huawei.com/consumer/cn/forum/topic/0201519912259900022?fid=0101271690375130218

unity接口文档参考:

https://docs.unity.cn/cn/Packages-cn/com.unity.huaweiservice@1.3/manual/gameservices_cn.html

以上是关于Unity集成GPT的主要内容,如果未能解决你的问题,请参考以下文章

安卓集成Unity开发示例

安卓集成Unity开发示例

Unity集成华为游戏服务SDK方式:集成Unity官方游戏SDK

「游戏引擎 浅入浅出」1.1 Unity的组成

Unity 游戏引擎教程?

Unity集成华为游戏服务SDK方式:Unity集成Android插件