【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望

这篇具有很好参考价值的文章主要介绍了【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

GPT for unity插件地址: GitHub - sunsvip/ChatGPTForUnity: ChatGPT for unity

用法:

  1. 打开Unity PackageManager界面.
  2. Add package from git URL
  3. 粘贴插件地址添加 https://github.com/sunsvip/ChatGPTForUnity.git

————————————————————————————————————

几个资本大佬花钱让一群程序员研发出了AI,砸了程序员的大锅。尤其是ChatGPT 4.0发布后,认识的同事朋友们都在恐慌AI的发展,甚至有不少人开始抗拒。我的观点是:人工智能是大势所趋,势不可挡,那就驾驭它吧!

我司已经在商业项目中实际使用了AI, 包括Stable Diffusion及其扩展插件,当然也有爆火的GPT。

Midjourney + Stable Diffusion + ControlNET + Lora以及Photoshop Stable Diffusion 等插件的结合使用已经强大到基本取代初中级原画师;

GPT 4.0势头已经咄咄逼人,据说下一代会进化到运行时处理功能,比如对磁盘的读写等。用户让“创建一个cs代码”,它就能在电脑硬盘里创建一个代码文件。个人觉得任重道远,功能越强责任越大,如果没有有效解决安全问题之前,这一步很难到来。

GPT已经能全面应用到游戏开发的各个环节了,策划的剧情设定、技术的代码编写优化、测试的测试用例等。我从去年12月开始使用,完全把它当成了一个搜索引擎,自从有了它几乎没使用多少次谷歌百度。4.0的到来彻底激发了我对ChatGPT实际应用的思考。

首先第一步肯定是先把GPT接入Unity,先建立起通讯,以此为基础各种应用功能才能百花齐放。

工具效果预览:

【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望
将回答里的代码保存成文件

【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望

 GPT接口实现:

用UnityWebRequest实现一个与ChatGPT通讯的类,之后的各种功能基于此类。

一,获取API Key

GPT提供了开放接口,仅需一个个人版的API Key即可, API Key获取入口:https://platform.openai.com/account/api-keys

【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望

 二,使用UnityWebRequest发送Post请求和接收GPT返回信息

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

上行数据结构如下:

{
  "messages": [
    {
      "role": "user",
      "content": "你是机器人吗"//要发送的问题
    }
  ],
  "model": "gpt-3.5-turbo",//AI数据模型
  "temperature": 0.7 //默认是1, 数值越大结果随机性越高
}

 需要注意的是,messages是个数组,如果想连续对话就需要把发送历史塞到这个messages数组,gpt根据你的发送历史分析上下文给出处理结果。gpt消耗token不是根据发送请求次数计算,聊天历史越多单次发送请求消耗的token越多,所以及时清除历史(新建话题)可以节省token消耗。

下行数据结构如下:

{
  "id": "chatcmpl-xxxxxxxxxxxxxxxxxx",
  "object": "chat.completion",
  "created": 1678987654,
  "model": "gpt-3.5-turbo-0301",
  "usage": {
    "prompt_tokens": 14,
    "completion_tokens": 23,
    "total_tokens": 37
  },
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "\n\n是的,我是一个AI语言模型,也可以被称为机器人。" //得到的回复
      },
      "finish_reason": "stop",
      "index": 0
    }
  ]
}

使用UnityWebRequest发送Post请求:

private IEnumerator Request(string input, Action<bool, string> onComplete, Action<float> onProgressUpdate)
        {
            var msg = new Message()
            {
                role = UserId,
                content = input,
            };
            requestData.AppendChat(msg);
            messageHistory.Add(msg);

            using (webRequest = new UnityWebRequest(ChatgptUrl, "POST"))
            {
                var jsonDt = UtilityBuiltin.Json.ToJson(requestData);
                Debug.Log(jsonDt);
                byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonDt);
                webRequest.uploadHandler = new UploadHandlerRaw(bodyRaw);
                webRequest.downloadHandler = new DownloadHandlerBuffer();
                webRequest.SetRequestHeader("Content-Type", "application/json");
                webRequest.SetRequestHeader("Authorization", $"Bearer {this.ApiKey}");
                //webRequest.certificateHandler = new ChatGPTWebRequestCert();
                var req = webRequest.SendWebRequest();
                while (!webRequest.isDone)
                {
                    onProgressUpdate?.Invoke((webRequest.downloadProgress + webRequest.uploadProgress) / 2f);
                    yield return null;
                }

                if (webRequest.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"---------ChatGPT请求失败:{webRequest.error}---------");
                    onComplete?.Invoke(false, string.Empty);
                }
                else
                {
                    var json = webRequest.downloadHandler.text;
                    Debug.Log(json);
                    try
                    {
                        ChatCompletion result = UtilityBuiltin.Json.ToObject<ChatCompletion>(json);
                        int lastChoiceIdx = result.choices.Count - 1;
                        var replyMsg = result.choices[lastChoiceIdx].message;
                        replyMsg.content = replyMsg.content.Trim();
                        messageHistory.Add(replyMsg);
                        onComplete?.Invoke(true, replyMsg.content);
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogError($"---------ChatGPT返回数据解析失败:{e.Message}---------");
                        onComplete?.Invoke(false, e.Message);
                    }
                }
                webRequest.Dispose();
                webRequest = null;
            }
        }

 以上就是向ChatGPT发送请求并接受回复的核心代码,非常简单。然而不出意外的话会出现请求报错:Cert verify failed: UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH, https证书验证失败。

所以还需要自定义验证类,直接跳过验证返回true:

class ChatGPTWebRequestCert : UnityEngine.Networking.CertificateHandler
    {
        protected override bool ValidateCertificate(byte[] certificateData)
        {
            //return base.ValidateCertificate(certificateData);
            return true;
        }
    }

然后为UnityWebRequest势力指定验证Handler:

webRequest.certificateHandler = new ChatGPTWebRequestCert();

再次运行就能正常接收数据了。

完整代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Unity.EditorCoroutines.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

namespace UnityGameFramework.Editor.AIAssistant
{
    public class ChatGPT
    {
        const string ChatgptUrl = "https://api.openai.com/v1/chat/completions";
        const string DefaultAPIKey = "替换自己的ChatGPT API Key";
        const string DefaultModel = "gpt-3.5-turbo";
        const float DefaultTemperature = 0;
        const string DefaultUserId = "user";
        string ApiKey;
        string UserId;
        List<Message> messageHistory;
        public List<Message> MessageHistory => messageHistory;
        ChatGPTRequestData requestData;
        UnityWebRequest webRequest;
        public float ChatGPTRandomness { get => requestData.temperature; set { requestData.temperature = Mathf.Clamp(value, 0, 2); } }
        public bool IsRequesting => webRequest != null && !webRequest.isDone;
        public float RequestProgress => IsRequesting ? (webRequest.uploadProgress + webRequest.downloadProgress) / 2f : 0f;
        public ChatGPT(string apiKey = DefaultAPIKey, string userId = DefaultUserId, string model = DefaultModel, float temperature = DefaultTemperature)
        {
            this.ApiKey = apiKey;
            this.UserId = string.IsNullOrWhiteSpace(userId) ? DefaultUserId : userId;
            messageHistory = new List<Message>();
            requestData = new ChatGPTRequestData(model, temperature);
        }
        /// <summary>
        /// 接着上次的话题
        /// </summary>
        public void RestoreChatHistory()
        {
            var chatHistoryJson = EditorPrefs.GetString("ChatGPT.Settings.ChatHistory", string.Empty);
            var requestDataJson = EditorPrefs.GetString("ChatGPT.Settings.RequestData", string.Empty);
            if (!string.IsNullOrEmpty(chatHistoryJson))
            {
                var jsonObj = UtilityBuiltin.Json.ToObject<ChatGPTRequestData>(requestDataJson);
                if (jsonObj != null)
                {
                    requestData.messages = jsonObj.messages;
                }
            }
            if (!string.IsNullOrEmpty(requestDataJson))
            {
                var jsonObj = UtilityBuiltin.Json.ToObject<List<Message>>(chatHistoryJson);
                if (jsonObj != null)
                {
                    messageHistory = jsonObj;
                }
            }
        }
        public void SaveChatHistory()
        {
            var chatHistoryJson = UtilityBuiltin.Json.ToJson(messageHistory);
            var requestDataJson = UtilityBuiltin.Json.ToJson(requestData);
            EditorPrefs.SetString("ChatGPT.Settings.ChatHistory", chatHistoryJson);
            EditorPrefs.SetString("ChatGPT.Settings.RequestData", requestDataJson);
        }
        public void Send(string message, Action<bool, string> onComplete = null, Action<float> onProgressUpdate = null)
        {
            EditorCoroutineUtility.StartCoroutine(Request(message, onComplete, onProgressUpdate), this);
        }

        public async Task<string> SendAsync(string message)
        {
            bool isCompleted = false;
            string result = string.Empty;
            Action<bool, string> onComplete = (success, str) =>
            {
                isCompleted = true;
                if (success) result = str;
            };

            EditorCoroutineUtility.StartCoroutine(Request(message, onComplete, null), this);
            while (!isCompleted)
            {
                await Task.Delay(10);
            }
            return result;
        }
        private IEnumerator Request(string input, Action<bool, string> onComplete, Action<float> onProgressUpdate)
        {
            var msg = new Message()
            {
                role = UserId,
                content = input,
            };
            requestData.AppendChat(msg);
            messageHistory.Add(msg);

            using (webRequest = new UnityWebRequest(ChatgptUrl, "POST"))
            {
                var jsonDt = UtilityBuiltin.Json.ToJson(requestData);
                Debug.Log(jsonDt);
                byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonDt);
                webRequest.uploadHandler = new UploadHandlerRaw(bodyRaw);
                webRequest.downloadHandler = new DownloadHandlerBuffer();
                webRequest.SetRequestHeader("Content-Type", "application/json");
                webRequest.SetRequestHeader("Authorization", $"Bearer {this.ApiKey}");
                webRequest.certificateHandler = new ChatGPTWebRequestCert();
                var req = webRequest.SendWebRequest();
                while (!webRequest.isDone)
                {
                    onProgressUpdate?.Invoke((webRequest.downloadProgress + webRequest.uploadProgress) / 2f);
                    yield return null;
                }

                if (webRequest.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"---------ChatGPT请求失败:{webRequest.error}---------");
                    onComplete?.Invoke(false, string.Empty);
                }
                else
                {
                    var json = webRequest.downloadHandler.text;
                    Debug.Log(json);
                    try
                    {
                        ChatCompletion result = UtilityBuiltin.Json.ToObject<ChatCompletion>(json);
                        int lastChoiceIdx = result.choices.Count - 1;
                        var replyMsg = result.choices[lastChoiceIdx].message;
                        replyMsg.content = replyMsg.content.Trim();
                        messageHistory.Add(replyMsg);
                        onComplete?.Invoke(true, replyMsg.content);
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogError($"---------ChatGPT返回数据解析失败:{e.Message}---------");
                        onComplete?.Invoke(false, e.Message);
                    }
                }
                webRequest.Dispose();
                webRequest = null;
            }
        }
        public void NewChat()
        {
            requestData.ClearChat();
            messageHistory.Clear();
        }
        public bool IsSelfMessage(Message msg)
        {
            return this.UserId.CompareTo(msg.role) == 0;
        }
    }

    class ChatGPTRequestData
    {
        public List<Message> messages;
        public string model;
        public float temperature;

        public ChatGPTRequestData(string model, float temper)
        {
            this.model = model;
            this.temperature = temper;
            this.messages = new List<Message>();
        }

        /// <summary>
        /// 同一话题追加会话内容
        /// </summary>
        /// <param name="chatMsg"></param>
        /// <returns></returns>
        public ChatGPTRequestData AppendChat(Message msg)
        {
            this.messages.Add(msg);
            return this;
        }
        /// <summary>
        /// 清除聊天历史(结束一个话题), 相当于新建一个聊天话题
        /// </summary>
        public void ClearChat()
        {
            this.messages.Clear();
        }
    }

    class ChatGPTWebRequestCert : UnityEngine.Networking.CertificateHandler
    {
        protected override bool ValidateCertificate(byte[] certificateData)
        {
            //return base.ValidateCertificate(certificateData);
            return true;
        }
    }
    class Usage
    {
        public int prompt_tokens;
        public int completion_tokens;
        public int total_tokens;
    }

    public class Message
    {
        public string role;
        public string content;
    }

    class Choice
    {
        public Message message;
        public string finish_reason;
        public int index;
    }

    class ChatCompletion
    {
        public string id;
        public string @object;
        public int created;
        public string model;
        public Usage usage;
        public List<Choice> choices;
    }
}

使用方法一, 同步获取结果:

var ai = new ChatGPT();
var str = await ai.SendAsync("你好");
Debug.Log(str);

 使用方法二, 异步获取结果:

new ChatGPT().Send("你好", (success, message) => { if (success) Debug.Log(message); }, requestProgress => { Debug.Log($"Request progress:{requestProgress}"); });

三,基于上面的类实现一个AI聊天窗口

为什么要写个聊天窗口:

1. https://chat.openai.com/chat 网页版登陆锁IP,并且会验证时区,如果用美国的节点时区时间对不上拒绝登录。

2. 虽然登录成功后不科学也能用,但是同一话题很快就会超时无法应答,刷新界面或新建话题才能正常使用,总之非常鸡肋。

而通过开放接口就没有这些问题,API请求会更加爽快。

聊天窗口功能设计:

1. 需要一个滚动列表展示双方对话记录,对话文本内容支持选择复制。

2. 问题输入框和发送按钮、新建话题(清除话题对话)

3. 对话历史存档。

代码实现,比较简单就不解释了,直接上源码:

using System;
using UnityEditor;
using UnityEngine;

namespace UnityGameFramework.Editor.AIAssistant
{
    [EditorToolMenu("AI助手/ChatGPT", 5)]
    public class ChatGPTWindow : EditorToolBase
    {
        public override string ToolName => "ChatGPT";

        Vector2 scrollPos = Vector2.zero;

        ChatGPT ai;
        private bool settingFoldout = false;
        string message;
        const string aiRoleName = "AI";
        private float chatBoxWidthRatio = 0.85f;
        private float iconSizeRatio = 0.6f;
        private float chatBoxPadding = 20;
        private float chatBoxEdgePadding = 10;

        GUIStyle myChatStyle;
        GUIStyle aiChatStyle;

        GUIStyle aiIconStyle;
        GUIStyle myIconStyle;
        GUIStyle txtAreaStyle;

        GUIContent chatContent;

        bool isEditorInitialized = false;
        private float scrollViewHeight;

        private void OnEnable()
        {
            EditorApplication.update += OnEditorUpdate;
            ai = new ChatGPT(AppBuildSettings.Instance.ChatGPTKey);
            ai.ChatGPTRandomness = AppBuildSettings.Instance.ChatGPTRandomness;
            chatContent = new GUIContent();
            ai.RestoreChatHistory();
        }

        private void OnEditorUpdate()
        {
            if (EditorApplication.isCompiling || EditorApplication.isUpdating)
            {
                return;
            }
            try
            {
                InitGUIStyles();
                isEditorInitialized = true;
                EditorApplication.update -= OnEditorUpdate;
            }
            catch (Exception)
            {

            }
        }

        private void InitGUIStyles()
        {
            aiChatStyle = new GUIStyle(EditorStyles.selectionRect);
            aiChatStyle.wordWrap = true;
            aiChatStyle.normal.textColor = Color.white;
            aiChatStyle.fontSize = 18;
            aiChatStyle.alignment = TextAnchor.MiddleLeft;

            myChatStyle = new GUIStyle(EditorStyles.helpBox);
            myChatStyle.wordWrap = true;
            myChatStyle.normal.textColor = Color.white;
            myChatStyle.fontSize = 18;
            myChatStyle.alignment = TextAnchor.MiddleLeft;


            txtAreaStyle = new GUIStyle(EditorStyles.textArea);
            txtAreaStyle.fontSize = 18;

            aiIconStyle = new GUIStyle();
            aiIconStyle.wordWrap = true;
            aiIconStyle.alignment = TextAnchor.MiddleCenter;
            aiIconStyle.fontSize = 18;
            aiIconStyle.fontStyle = FontStyle.Bold;
            aiIconStyle.normal.textColor = Color.black;
            aiIconStyle.normal.background = EditorGUIUtility.FindTexture("sv_icon_dot5_pix16_gizmo");

            myIconStyle = new GUIStyle(aiIconStyle);
            myIconStyle.normal.background = EditorGUIUtility.FindTexture("sv_icon_dot2_pix16_gizmo");
        }

        private void OnDisable()
        {
            ai.SaveChatHistory();
        }
        private void OnGUI()
        {
            if (!isEditorInitialized) return;
            EditorGUILayout.BeginVertical();
            {
                scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
                {
                    scrollViewHeight = 0;
                    foreach (var msg in ai.MessageHistory)
                    {
                        var msgRect = EditorGUILayout.BeginVertical();
                        {
                            EditorGUILayout.BeginHorizontal();
                            {
                                bool isMyMsg = ai.IsSelfMessage(msg);
                                var labelStyle = isMyMsg ? myChatStyle : aiChatStyle;
                                chatContent.text = msg.content;
                                float chatBoxWidth = this.position.width * chatBoxWidthRatio;
                                float iconSize = (this.position.width - chatBoxWidth) * iconSizeRatio;
                                float chatBoxHeight = Mathf.Max(iconSize, chatBoxEdgePadding + labelStyle.CalcHeight(chatContent, chatBoxWidth - chatBoxEdgePadding));
                                if (isMyMsg) { GUILayout.FlexibleSpace(); }
                                else
                                {
                                    EditorGUILayout.LabelField(aiRoleName, aiIconStyle, GUILayout.Width(iconSize), GUILayout.Height(iconSize));
                                }
                                EditorGUILayout.SelectableLabel(msg.content, labelStyle, GUILayout.Width(chatBoxWidth), GUILayout.Height(chatBoxHeight));
                                if (!isMyMsg) { GUILayout.FlexibleSpace(); }
                                else
                                {
                                    EditorGUILayout.LabelField(msg.role, myIconStyle, GUILayout.Width(iconSize), GUILayout.Height(iconSize));
                                }
                                EditorGUILayout.EndHorizontal();
                            }
                            EditorGUILayout.EndVertical();
                        }
                        EditorGUILayout.Space(chatBoxPadding);
                        scrollViewHeight += msgRect.height;
                    }
                    EditorGUILayout.EndScrollView();
                }

                if (ai.IsRequesting)
                {
                    var barWidth = position.width * 0.8f;
                    var pBarRect = new Rect((position.width - barWidth) * 0.5f, (position.height - 30f) * 0.5f, barWidth, 30f);
                    EditorGUI.ProgressBar(pBarRect, ai.RequestProgress, $"请求进度:{ai.RequestProgress:P2}");
                }
                GUILayout.FlexibleSpace();
                if (settingFoldout = EditorGUILayout.Foldout(settingFoldout, "展开设置项:"))
                {
                    EditorGUILayout.BeginVertical("box");
                    {
                        EditorGUILayout.BeginHorizontal();
                        {
                            EditorGUILayout.LabelField("ChatGPT API Key:", GUILayout.Width(170));
                            AppBuildSettings.Instance.ChatGPTKey = EditorGUILayout.TextField(AppBuildSettings.Instance.ChatGPTKey);
                            EditorGUILayout.EndHorizontal();
                        }

                        EditorGUILayout.BeginHorizontal();
                        {
                            EditorGUILayout.LabelField("结果随机性:", GUILayout.Width(170));
                            ai.ChatGPTRandomness = AppBuildSettings.Instance.ChatGPTRandomness = EditorGUILayout.Slider(AppBuildSettings.Instance.ChatGPTRandomness, 0, 2);
                            EditorGUILayout.EndHorizontal();
                        }
                        EditorGUILayout.EndVertical();
                    }

                }
                //EditorGUILayout.LabelField(scrollPos.ToString());
                EditorGUILayout.BeginHorizontal();
                {
                    message = EditorGUILayout.TextArea(message, txtAreaStyle, GUILayout.MinHeight(80));

                    EditorGUI.BeginDisabledGroup(ai.IsRequesting);
                    {
                        if (GUILayout.Button("发送消息", GUILayout.MaxWidth(120), GUILayout.Height(80)))
                        {
                            if (!string.IsNullOrWhiteSpace(message))
                            {
                                ai.Send(message, OnChatGPTMessage);
                            }
                        }
                        if (GUILayout.Button("新话题", GUILayout.MaxWidth(80), GUILayout.Height(80)))
                        {
                            ai.NewChat();
                        }
                        EditorGUI.EndDisabledGroup();
                    }

                    EditorGUILayout.EndHorizontal();
                }
                EditorGUILayout.EndVertical();
            }
        }

        private void OnChatGPTMessage(bool arg1, string arg2)
        {
            scrollPos.y = scrollViewHeight;
            if (arg1)
            {
                message = string.Empty;
            }
            Repaint();
        }
    }
}

添加代码后,Toolbar的Tools工具栏会自动识别这个工具菜单,点击即可打开AI对话窗口:

【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望

 AI的应用展望:

下一步就是为GPT赋予双手,添加各种指令Handler。比如生成json文件、生成语言国际化Excel文件、修改优化代码、生成代码文件、生成Shader、一键拼UI等等。

分为三个模块:

1. 描述文本(发送给GPT)

2. 动态追加描述内容:有时需要追加一些文本数据,比如让GPT优化一段代码,需要动态追加把代码补充到描述文本。

3. 结果解析。得到目标结果,使用Handler解析GPT返回结果,达成某种功能。GPT返回的代码或json等数据都会用标签包住,通过解析标签就可以生成各种类型的文件。

最终就可以不用写程序,只写问题的描述文本,确保能从GPT得到满意答案就可以实现某项功能。想要新增新的工具,扩展新的功能只需要在文件中添加修改问题描述文本即可。

比如语言国际化,我通过问题描述让GPT从工程代码中扫描所有语言本地化函数GF.Localization.GetText()传入的国际化文本,并且把文本翻译成中文,把结果以key,value键值对保存输出json文件。最后我得到了GPT返回的诸如{"Hello":”你好“}的所有国际化文本和翻译结果。

然后我只需要解析GPT返回结果,生成语言国际化文件到工程中就完成了AI自动处理语言国际化的问题。文章来源地址https://www.toymoban.com/news/detail-476563.html

到了这里,关于【Unity】AI实战应用——Unity接入GPT和对游戏开发实际应用的展望的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【大厂AI课学习笔记NO.51】2.3深度学习开发任务实例(4)计算机视觉实际应用的特点

    今天考试通过腾讯云人工智能从业者TCA级别的认证了! 还是很开心的,也看不到什么更好的方向,把一切能利用的时间用来学习,总是对的。 我把自己考试通过的学习笔记,都分享到这里了,另外还有一个比较全的思维脑图,我导出为JPG文件了。下载地址在这里:https://do

    2024年03月14日
    浏览(46)
  • JavaScript应用:五子棋游戏实战开发

    🏆作者简介,黑夜开发者,全栈领域新星创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:100个JavaScript的小应用。 🎉欢迎 👍点赞✍评论⭐收藏 五子棋是一

    2024年02月13日
    浏览(45)
  • Unity手机游戏开发:从搭建到发布上线全流程实战

    前言: 技术书籍是学习技术知识的重要资源之一。读技术书可以帮助我们学习新技能和知识,技术书籍提供了可靠的、全面的信息,帮助我们快速学习新技能和知识。同时技术书籍有助于保持你的竞争力,因为它们提供了最新的技术知识和实践。这在当今快速发展的技术领域

    2024年01月22日
    浏览(66)
  • 【unity项目实战】3DRPG游戏开发07——其他详细的设计

    参考原视频链接: 【视频】:https://space.bilibili.com/370283072 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入

    2024年02月05日
    浏览(48)
  • 【游戏开发实战】Unity实现类似GitHub地球射线的效果(LineRenderer | 贝塞尔曲线)

    一、前言 嗨,大家伙,我是新发。 好久不见,这是2022年第一篇博客,今天有同学私信我,问我在 Unity 中如何实现这种地球辐射线的效果, 这一看,我就想到了 GitHub 主页的地球射线, 那么,今天就来讲讲如何实现这个效果吧~ 本文最终效果如下: 本文工程源码见文章末尾

    2024年02月06日
    浏览(96)
  • 「GPT虚拟直播」实战篇|GPT接入虚拟人实现直播间弹幕回复

    ChatGPT和元宇宙都是当前数字化领域中非常热门的技术和应用。结合两者的优势和特点,可以探索出更多的应用场景和商业模式。例如,在元宇宙中使用ChatGPT进行自然语言交互,可以为用户提供更加智能化、个性化的服务和支持;在ChatGPT中使用元宇宙进行虚拟现实体验,可以

    2024年02月06日
    浏览(55)
  • 【游戏开发实战】Unity手游第一人称视角,双摇杆控制,FPS射击游戏Demo(教程 | 含Demo工程源码)

    一、前言 嗨,大家好,我是新发。 有同学私信我,问我能不能写一篇Unity手游第一人称视角控制的教程, 那么,今天就来做个 Demo 吧~ 注: Demo 工程源码见文章末尾 最终效果如下: 二、实现方案 1、无主之地,第一人称视角 第一人称视角的游戏大家应该不陌生,比如《无主

    2023年04月08日
    浏览(52)
  • Unity上接入手柄,手柄控制游戏物体移动

    1、unity软件上安装system input 组件。菜单栏【window】-【Packag Manager】打开如下界面,查找Input System,并且安装。 2、安装成功后插入手柄到windows上,打开菜单栏上【window】--【Analysis】--【Input Debuger】 进入Input Debug界面,可以看到手柄设备能被Unity识别。 3、双击【XinputControllerW

    2024年04月15日
    浏览(51)
  • 苹果眼镜(Vision Pro)的开发者指南(6)-实战应用场景开发 - 游戏、协作、空间音频、WebXR

    第一部分:【构建游戏和媒体体验】 了解如何使用visionOS在游戏和媒体体验中创建真正身临其境的时刻。游戏和媒体可以利用全方位的沉浸感来讲述令人难以置信的故事,并以一种新的方式与人们联系。将向你展示可供你入门的visionOS游戏和叙事开发途径。了解如何使用Real

    2024年01月24日
    浏览(52)
  • AI 大模型应用开发实战纲要

    初探大模型:起源与发展 预热篇:解码注意力机制(Attention ) 变革里程碑:Transformer 的崛起 走向不同:GPT 与 Bert 的选择 GPT 模型家族:从始至今 GPT 模型家族:从始至今 从 GPT-1 到 GPT-3.5:一路的⻛云变幻 ChatGPT:赢在哪里 GPT-4:一个新的开始 大模型的未来:开源力量

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包