草庐IT

最新完整热更新实战案例学习,包括资源热更新及代码热更新【文末送书】

呆呆敲代码的小Y 2023-04-18 原文

  • 🎬 博客主页:https://xiaoy.blog.csdn.net

  • 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉

  • 🎄 学习专栏推荐:Unity系统学习专栏

  • 🌲 游戏制作专栏推荐:游戏制作

  • 🌲Unity实战100例专栏推荐:Unity 实战100例 教程

  • 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 📆 未来很长,值得我们全力奔赴更美好的生活✨

  • ------------------❤️分割线❤️-------------------------

Unity 热更新技术最新系列全面教程


Unity 热更新技术 |(七)完整热更新实战案例学习使用,包括资源热更新及代码热更新

前言

  • 开始学习热更新方面系列知识,就从这一篇开始吧!
  • 本系列教程 会从热更新基本概念出发,详细介绍热更新相关的全套知识点。
  • 如热更新技术基本原理、热更新主流方案、AssetBundle系列教程、Lua语言编程、Lua与Unity交互教程、Xlua框架使用、热更新实战教程等方面。
  • 热更新作为一个开发者必备技能,如果想学习的话,可以从现在开始了哦~
  • 接下来从热更新实战案例学习使用 开始学习吧!

一、xLua基础配置及使用方法

本篇文章会正式使用xLua完成一个简单的热更新实战案例,关于xLua的基本配置及导入的详细信息可以参考下面这篇文章:
Unity 热更新技术 |(六)xLua框架学习最新系列完整教程


二、Unity中的基本配置

2.1 开启宏 HOTFIX_ENABLE

File -> Bulid Setting -> Player Settings -> Player -> Other Setting -> Scripting Define Symbols下添加 HOTFIX_ENABLE

添加完之后点击Apply,菜单栏中会出现一个新的选项Hotfix Injece In Editor。
若是未出现该选项,则重启该Unity 项目即可。

2.2 将xLua 中的Tools 工具文件夹 复制到热更新工程中Assets同级目录

若是会看到报错,原因是因为有重复文件导致的,删除下图里的xlua,Xlua.Mini3个文件即可,Plugins/x86_64路径下的xlua也删掉即可


三、xLua在Unity中使用步骤

  1. 每次修改需要更新的脚本,需要运行Generate Code
  2. 执行Hotfix Inject In Editor,进行Lua注入。

检查Unity 中XLua热更新环境

  1. 引入命名空间 using XLua
  2. 在需要更新的类上方加入标签 [Hotfix]
  3. 在需要更新的方法上方加入 [LuaCallCSharp]
  4. 创建 LuaEnv
  5. 将 测试脚本HotfixTest 挂载到场景中。
  6. 执行 Generate Code
  7. 执行 Hotfix Inject In Editor ,进行Lua注入。
  8. 运行结果,lua虚拟环境搭建完毕。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;

    [Hotfix]
    public class HotfixTest : MonoBehaviour
    {
        public LuaEnv luaEnv;
        // Start is called before the first frame update
        void Start()
        {
            luaEnv = new LuaEnv();
            luaEnv.DoString("CS.UnityEngine.Debug.Log('hello world')");
            Debug.Log("Unity_Hello World!");
            luaEnv.Dispose();
        }
    }

运行结果如下:


四、AB包资源打包

关于AB包更多使用详情信息可查看文章:Unity 热更新技术 | (二) AssetBundle - 完整系列教程学习

记得要将AssetBundles-Browser解压后的Editor文件夹Copy到Unity的项目中。目录结构如下图所示。

此处直接介绍具体步骤,不再对AssetsBundle做过多赘述,有不明白的可以参考上述文章。

4.1实战场景构建

本次实战场景为玩家在场景中可以四处移动和旋转,按住鼠标左键可以向前方发射子弹。

先搭建一个简易场景并编写相关功能代码,场景及脚本如下:

public class PlayerController : MonoBehaviour
{
    public float moveSpeed = 10f;
    public float turnSpeed = 100f;
    public float fireTime = 0.5f;

    private float ver;
    private float hor;
    private float timer;
    
    void Update()
    {
        InputControl();
    }
    private void InputControl()
    {
        ver = Input.GetAxis("Vertical");
        hor = Input.GetAxis("Horizontal");

        transform.position += transform.forward * ver * Time.deltaTime * moveSpeed;
        transform.Rotate(transform.up * hor * Time.deltaTime * turnSpeed);

        if (Input.GetMouseButton(0))
        {
            if (timer <= 0)
            {
                //发射子弹
				//
                timer = fireTime;
            }
            else
            {
                timer -= Time.deltaTime;
            }
        }
    }
}

添加一个简易的UI界面UIDemo,用于游戏开始和结束,也拖成预制体。

4.2 将玩家、子弹和UI预制体打到AB包中

首先将玩家和子弹对象 拖成预制体,并设置AB包的名称。

我这里给玩家和子弹加了两个材质,也一并打到AB包中。

包括UI预制体以及新添加了两张图片素材也一并打成AB包,如下图所示:

然后点击Window -> AssetBundles Browser 进行打包。
更多AB内容可以查看文章:Unity 热更新技术 | (二) AssetBundle - 完整系列教程

这里就直接进行Build了。

Build之后会出现几个AB包文件,后续就是加载这几个文件进行AB包加载并获取其中的对象。

4.3 加载AB包中的玩家和子弹 并进行实例化

创建加载AB包的脚本方法 ABLoadManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ABLoadManager : MonoBehaviour
{
    private AssetBundle ab;
    private static ABLoadManager instance;
    public static ABLoadManager GetInstance()
    {
        if (instance != null)
        {
            return instance;
        }
        else
        {
            return new ABLoadManager();
        }
    }

    private void Awake()
    {
        instance = this;
    }

    /// <summary>
    /// 根据AB包名字加载AB包
    /// </summary>
    public void LoadAB(string packageName)
    {
        //加载指定AB包
        ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/"+ packageName);
        //加载主包
        AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "StandaloneWindows");
        //加载主包中的固定文件
        AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        //从固定文件中得到依赖信息
        string[] strs = abManifest.GetAllDependencies(packageName);
        //得到依赖包的名字并加载
        foreach (var s in strs)
        {
            AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + s);
        }
    } 

    /// <summary>
    /// 根据预制体名称获取对象
    /// </summary>
    /// <param name="objName"></param>
    /// <returns></returns>
    public GameObject GetABGameObject(string objName)
    {
        GameObject abGO = ab.LoadAsset(objName, typeof(GameObject)) as GameObject;
        return abGO;
    }

然后在GameManager.cs 中先对UI预制体进行加载:

public class GameManager : MonoBehaviour
{
    private Transform canvas;

    private void Awake()
    {
        canvas = GameObject.Find("Canvas").transform;
    }
    void Start()
    {
        ABLoadManager.GetInstance().LoadAB("ui");
        Instantiate(ABLoadManager.GetInstance().GetABGameObject("UIDemo"), canvas);
    }
}

之后在GameController.cs中添加UI相关的方法,代码如下所示:

public class GameController : MonoBehaviour
{
    public Button btn_Start;
    public Button btn_Quit;
    public Image image_BG;

    private bool isPlay;
    //public LuaEnv luaenv;

    private void Awake()
    {
        isPlay = false;
        btn_Start.onClick.AddListener(StartGame);
        btn_Quit.onClick.AddListener(QuitGame);
    }

    private void StartGame()
    {
        if (isPlay) return;
        isPlay = true;

        //加载AB包,获取图片素材
        ABLoadManager.GetInstance().LoadAB("texture");
        image_BG.sprite = ABLoadManager.GetInstance().GetABSprite("common_btn");
        btn_Start.image.sprite = ABLoadManager.GetInstance().GetABSprite("common_btn");
        btn_Quit.image.sprite = ABLoadManager.GetInstance().GetABSprite("common_btn");

        //加载AB包,实例化玩家
        ABLoadManager.GetInstance().LoadAB("module");
        GameObject player = Instantiate(ABLoadManager.GetInstance().GetABGameObject("Player"), new Vector3(0, 0, 1), Quaternion.identity);
    }
    private void QuitGame()
    {
#if UNITY_EDITOR //如果是在编辑器环境下
        UnityEditor.EditorApplication.isPlaying = false;
#else//在打包出来的环境下
    Application.Quit();
#endif
    }
}

其中GameManager和ABLoadManager挂载到场景中,GameController挂载到UIDemo上面。

此时AB包的内容就算是暂时做完了,运行看一下效果:


打包成exe文件查看效果:

这样在开始运行之后,会从uiAB包中加载UIDemo并实例化,然后点击开始之后会从texture AB包中加载素材并赋值给Image组件,然后从module AB包中加载并实例化玩家。

当玩家按下鼠标左键时,从AB包中加载子弹并实例化发射子弹。

这样一个简单的Demo就制作好了,下面开始正式进行资源热更新和代码热更新的操作。


五、资源热更新

先来讲一下资源热更新,一般是用于项目中的资源替换,比如UI素材替换,预制体替换(材质/网格等)。
资源热更新使用Unity的AssetsBundle就可以做到,下面就用一个简单的案例来演示一下资源的热更新。

目的:利用AB包对项目中的UI素材和子弹的材质进行替换。

在上面我们已经构建了一个简单的场景并且可以运行了,下面在Unity中把子弹的颜色由原来的红色材质替换为绿色材质。

只需要在子弹预制体中将绿色的材质球拖到子弹上即可

然后再找一个新的素材拖到项目中,将名字改为common_btn,并将原来的那张图片删除或者改个别的名字,记得将新的素材也要设置AB包名称。

然后重新打开Window -> AssetBundle Browser 并进行Build。

此时打开我们刚才已经打包成exe的文件夹,将刚才Build的AB包进行替换。


替换前后对比如下
替换前:

替换后:

此时我们可以看到,在打包后的文件夹中只需要对AB包进行替换就可以完成一次资源的热更新,而无需重新从Unity重新打包即可生效。

在正常的游戏项目中如果遇到某些活动,游戏中的UI界面就会发生变化,此时就用到了热更新中的资源热更新。
只需要在玩家打开游戏时检查游戏的版本号,若需要进行更新,则从服务器中下载对应的AB包,然后将原来的包进行替换就可以实现该效果了。

资源热更新也可以通过代码热更新来实现,只需要将对应资源的调用代码进行更新替换同样也可以做到资源的热更新。
下面就来看看代码热更新怎样做到吧,这块属于本文的重点内容。


六、代码热更新(重点)

若是整个游戏项目都使用Lua脚本完成,那在打包后的游戏中直接对Lua脚本替换就可以实现代码的一次热更新。
因为Lua语言的特性如此,所以不向C#一样需要重新编译后才可以实现功能。

若项目原来使用的C#实现,现在需要使用到热更新,那就需要下面的方法来进行了,也就是利用了xLua的一个热补丁特性。

xLua所有的配置都支持三种方式:打标签;静态列表;动态列表。
配置有两必须两建议:

  • 列表方式均必须是static的字段/属性
  • 列表方式均必须放到一个static类
  • 建议不用标签方式
  • 建议列表方式配置放Editor目录(如果是Hotfix配置,而且类位于Assembly-CSharp.dll之外的其它dll,必须放Editor目录)

更多内容可以来XLua文章查看:Unity 热更新技术 |(六)xLua框架学习最新系列完整教程

下面的测试用例使用打标签([Hotfix])的方式练习,就是在需要进行热更的类上面添加 [Hotfix] 特性。

6.1 在Resources创建lua文件夹保存lua脚本,unity中加载lua文件要以.lua.txt结尾,否则Unity不识别.lua文件

6.2 创建LuaEnv 脚本管理LuaManage并自定义加载器MyLoader。

using System.IO;
using UnityEngine;
using XLua;
public class LuaManager : MonoBehaviour
{
    public static LuaManager _instance;
    public static LuaManager Instance
    {
        get
        {
            return _instance;
        }
    }
    [CSharpCallLua]
    public delegate void LuaDelegate(string paras);
    /// <summary>
    /// 定义一个Delegate,Lua结果将传参回调给该Delegate
    /// </summary>
    public static LuaDelegate LuaFunc;
    /// <summary>
    /// 定义一个Lua虚拟机,建议全局唯一
    /// </summary>
    public static LuaEnv luaEnv;
    public LuaEnv GetLuaEnv()
    {
        return luaEnv;
    }
    void Awake()
    {
        _instance = this;
        LuaEnvInit();
    }
    public void LuaEnvInit()
    {
        luaEnv = new LuaEnv();
        luaEnv.AddLoader(MyLoader);
        ///lua脚本的主入口
        luaEnv.DoString("require 'updateInfo'");
        //获取Lua中全局function,然后映射到delegate
        luaEnv.Global.Get("LuaFunc", out LuaFunc);
    }
    private byte[] MyLoader(ref string filepath)
    {
        string abspath = Application.dataPath + "/Resources/lua/" + filepath + ".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(abspath));
    }
}

6.3 先来个进行测试,在lua文件夹中创建名为hello.lua.txt

--将GameManager脚本中的Test方法替换为下列ChangeCode方法
xlua.hotfix(CS.GameManager,'Test',function(self)
CS.UnityEngine.Debug.Log("Hello Lua!")
end) 

然后在GameManager.cs中添加一个Test方法,如下所示:

此时点击运行Generate Code在执行Hotfix Inject In Editor,开始运行,效果如下:

这样lua脚本更新GameManager脚本中的Test方法输出"Hello Lua!"

GameManager中的Test()中的内容已经由hello.lua替换成功啦!
这也算是一个最最入门的热更新完成啦~

6.4 修改 PlayerController.cs 脚本,在代码中添加一个 Test() 和 Jump() 用于测试。

using UnityEngine;
using XLua;

[Hotfix]
public class PlayerController : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float turnSpeed = 500f;
    public float fireTime = 0.5f;

    private float ver;
    private float hor;
    private float timer;

    private void Start()
    {
        Test();
    }
    void Update()
    {
        InputControl();
    }

    private void InputControl()
    {
        ver = Input.GetAxis("Vertical");
        hor = Input.GetAxis("Horizontal");

        transform.position += transform.forward * ver * Time.deltaTime * moveSpeed;
        transform.Rotate(transform.up * hor * Time.deltaTime * turnSpeed);

        if (Input.GetMouseButton(0))
        {
            if (timer <= 0)
            {
                //从AB包中 加载 并实例化子弹
                GameObject go = Instantiate(ABLoadManager.GetInstance().GetABGameObject("Bullet"), transform.GetChild(0).position, Quaternion.identity);
                go.GetComponent<Rigidbody>().AddForce(transform.forward * 10,ForceMode.Impulse);
                Destroy(go, 10f);
                timer = fireTime;
            }
            else
            {
                timer -= Time.deltaTime;
            }
        }
        Jump();
    }

    public void Test()
    {
        Debug.Log("1测试热补丁。");
    }
    public void Jump()
    {
        Debug.Log("2测试热补丁。");
    }
}

6.5 热更新变量添加

xlua.util提供了auto_id_map函数,执行一次后你就可以像以前那样直接用类,方法名去指明修补的函数。

可以在xLua源码中找到util.lua.txt 并copy到Assets\Resources\lua中。
创建updateInfo.lua.txt编写脚本引入util,require 'util’即可使用。

在lua文件夹中创建名为updateInfo.lua.txt,代码如下:

require "util"

--将PlayerController脚本中的Test()替换为下列ChangeCode方法
xlua.hotfix(CS.PlayerController,'Test',function(self)
ChangeCode(self)
print("Fixed PlayerController!")
end) 
function ChangeCode(self)
   -- 改变玩家的射速和旋转速度
   self.fireTime = 0.05
   self.turnSpeed = 1000
end

--将PlayerController脚本中的Jump()替换为下列ChangeCode方法
xlua.hotfix(CS.PlayerController,'Jump',function(self)
JumpCode(self)
end)
function JumpCode(self)
    -- 给玩家增加一个按下鼠标右键跳跃的功能
    local inputSpace = CS.UnityEngine.Input.GetMouseButtonDown(1)
    if inputSpace then
        self:GetComponent("Rigidbody").velocity = self.transform.up * 10;
    end
end 

此时运行游戏,就可以发现玩家的射速、旋转速度已经发生变化,并且还多了一个按下鼠标右键跳跃的功能!

更新前:

更新后:

若是出现报错(要排除没有手动Generate Code -> Hotfix Inject In Editor),可查看相关文章
https://www.freesion.com/article/9584121931/
https://blog.csdn.net/qq_43420347/article/details/106441441
https://github.com/tencent/xlua/issues/383

本文中出现的项目资源可以在文末卡片中回复 xLua热更新练习获取。


总结

  • 使用热更新最大的好处是我们将游戏项目Build完之后,可以通过直接修改Lua文件来更新游戏中的功能而无需重新编译!
  • AssetBundle和lua代码放到了服务端,当玩家连接到服务器,检查AssetBundle和Lua代码更新,如需要更新就把新内容下载到本地。
  • 此外使用MD5校验,可以检查哪些内容需要更新。
  • 比如上述增加的跳跃功能就可以通过增加一个Lua文件来完成而不用重新对游戏项目代码修改然后进行打包Build。
  • 本文介绍了热更新的基本配置及实战联系,包括资源热更新和代码热更新。
  • 由于是热更新实战练习,所以热更的内容比较少。
  • 但是在实际项目中可能需要热更新的内容就会非常多,这个时候一般都是会使用一个封装的热更新框架来实现。
  • 然后使用封装好的方法将项目中可能会出现热更新的地方配置好,在需要热更的时候执行相关Lua文件就好啦。
  • 若是觉得 热更新系列教程 不错的话可以推荐给其他小伙伴学习哦,在此感谢~

系列文章地址


👑评论区抽奖送书

最后在评论区进行抽取三名幸运的小伙伴送下面这本书籍

在这里搞个小活动抽奖送给大家,对看书感兴趣的小伙伴可以参加一波呀,抽中概率很大哦!

《Unity手机游戏开发:从搭建到发布上线全流程实战》

尤其是想从事Unity开发刚入门的小伙伴,这本书就可以让你了解相关知识,对症下药可以极大地提高学习效率!

🎁规则

规则如下:

🚀 规则如下🚀
  • 给本篇博客文章 点赞 收藏 评论 三连,然后就可以在博客文章评论区抽奖送一本Python的书籍!

  • 总共抽三本,中的几率还是很大的哦~ 想看书的小伙伴参与起来!

  • 中奖信息文章发布时间的三天后下午本篇文章评论区公布!记得留意呀!

  • 没抽到的,但是喜欢这本书的小伙伴也可以在网上自行购买哈,官方正品商店购买即可!

🚀 规则如上🚀

🎄推荐理由(⭐⭐⭐⭐⭐)

  • 游戏大厂资深主程结合9年游戏开发经验和3年高校实际教学经验,钻研上百款手游案例
  • 总结了自身从初学者成长为技术总监的成长之路,为Unity初学者倾心打造一条全流程实践路线,帮助初学者开发并上线符合标准的开放世界类手游。
  • 附赠8节教学视频和3GB多案例工程源文件。
  • 本书将以一款开放世界类游戏的实践过程为主线,为读者呈现从零开始上线一款游戏的实践路线、游戏引擎Unity的开发模式,以及游戏开发的核心框架。

    没抽到的小伙伴也可以官方平台自行购买哦:https://item.jd.com/13557443.html
    如果实在喜欢但是没抽到你的话,可以在评论区说一下,后续可以再给大家继续送福利!

有关最新完整热更新实战案例学习,包括资源热更新及代码热更新【文末送书】的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  8. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  9. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  10. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

随机推荐