Unity大场景切换进行异步加载时,如何设计加载进度条,并配置滑动条按照的曲线给定的速率滑动

news2025/1/12 6:04:47

请添加图片描述

一、异步加载场景的过程

1、异步加载场景用到的API

LoadSceneAsync

2、异步加载的参数说明

  • (1)默认参数:SceneManagement.LoadSceneAsync(“SceneName”);
AsyncOperation task = SceneManager.LoadSceneAsync("SceneName");
  • (2)异步加载时的两种加载模式-Single和Additive
    请添加图片描述
    关于【活动场景】和【非活动场景】有些什么差异,本文不做讨论。
//定义加载任务
AsyncOperation loadTask = SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Additive);
//AsyncOperation loadTask = SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Single);

await loadTask;                          //实际加载过程
  • (3)Single异步加载的流程
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("SceneName", LoadSceneMode.Single);

加载的步骤解释:

步骤进度值事项描述
第一步0% ~ 90%把资源加入到内存中
第二步初始化新加入的场景,激活新加入的场景,设置为【活动场景】
第三步新场景激活后,原来的场景会被卸载和清理
第四步asyncLoad.isDone设置为true当 isDone 属性为 true 时,表示场景切换已完成,新场景已经完全加载并激活,旧场景已经被卸载。

加载过程:

  • 1、进度值:0%~90% 加载新场景,当到进度值达到90%时,代表场景资源已经加入到内存中,后面10%的时间留给新旧场景的显示切换、新场景初始化、旧场景资源回收。
  • 2、场景要如何切换,【自动显示】还是【代码手动控制】它显示

下面是加载完毕自动显示:

AsyncOperation task = SceneManager.LoadSceneAsync("SceneName");
await loadTask;  

下面是手工控制场景的显示

//定义加载任务
AsyncOperation loadTask = SceneManager.LoadSceneAsync("SceneName");
loadTask.allowSceneActivation = false;   //加载完毕场景不立即显示

await loadTask;                          //实际加载过程

//此处,用户要进行其他操作,比如点击一个按钮,把数据上传到服务器
//...

loadTask.allowSceneActivation = true;    //设置成true后,系统开始后续的10%的工作,会把新场景显示,把老场景卸载

二、大场景切换面临的问题

1、理想情况下的加载

  • (1)、先定义一个Progress的对象(进度报告器),相当于一个事件,当进度值有变化的时候,就会回调该方法。
  • (2)、异步加载资源,并把Progress对象绑定到加载过程。
// 定义进度报告器
var progress = new Progress<float>(value =>
{     
    //更新滑动条进度
    Debug.Log($"加载进度: {value * 100}%");
});

//实际加载
await SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Single).ToUniTask(progress: progress);   

2、实际加载情况

  • (1)、存在的问题
    要加载的是小场景时,进度报告非常丝滑,一点也不卡顿。
    但是,让要加载的是大场景的时候,update主线程卡死,进度不会走,一直在0%,等几秒钟之后,加载完毕时,进度突然跳成100%,这就太刺激了。
    测试环境说明:Unity2021.3.40

  • (2)、改进方法
    把进度条改成加载前、加载中和加载后,真正的加载放在【加载中】。

三、进度条的设计

(1)如何划分进度条

我们把进度条分成三个部分,如下图的阶段一、二、三。
我们把加载的真正过程放在阶段一和阶段二之间,加载时,进度条暂停不动。
为了看起来丝滑一些,我们把进度条设置曲线动画
在这里插入图片描述

(2)加载效果

请添加图片描述

四、如何给进度条配上曲线动画

如何给滑动条设置曲线动画,如下图所示,在1秒内,让滑块从0%跑到33%,跑的时- 候不匀速,而是先快后慢。

(1)曲线运动速度的设置

public class JumpScene : MonoBehaviour
{
    /// <summary>
    /// 【第一段进度条动画】的动画曲线
    /// </summary>
    [Header("【第一段进度条动画】的动画曲线")]
    public AnimationCurve startAnim;
    //......
}

在面板上设置曲线速率
在这里插入图片描述

(2)曲线速率与运动的实现:按照给定的曲线速度运动,而不是匀速运动

public async UniTask test4()
{
    var progress = 0.0f;         //当前累计耗时
    var duration = 3f;           //给定的动画时间,3秒
    var progressCurve = 0f;      //曲线进度,按照曲线速度运动,而不是匀速运动
    while (true)
    {
        progress += Time.deltaTime;
        progressCurve = startAnim.Evaluate(progress / duration) / duration;            
        Debug.Log(progressCurve);
        if (progress > duration) break;
        await UniTask.Yield();
    }
}

五、主要代码

(1)过程说明

大场景加载的时候,异步加载的进度值会卡死,因为update主线程卡死了
(无论是协程还是用异步,都没有改观,都是卡死状态)。
出现该情况的时候,进度会卡住,直到加载完毕,进度值突然从【0%】调到【90%】,
90%代表资源加载完毕,余下10%的时间是用来进行场景显示和资源回收处理的。
1、前面三分之一:初始化…
2、…实际加载…
3、中间三分之一:假装在加载…
4、后面三分之一:加载后资源处理…实际加载的时候,资源调入完毕时进度

(2)代码清单

/// <summary>
/// 场景跳转:异步加载一个场景,显示进度条,进度条滑动动画
/// 
/// **************************************************************************
/// 大场景加载的时候,异步加载的进度值会卡死,因为update主线程卡死了
/// (无论是协程还是用异步,都没有改观,都是卡死状态)。
/// 出现该情况的时候,进度会卡住,直到加载完毕,进度值突然从【0%】调到【90%】,
/// 90%代表资源加载完毕,余下10%的时间是用来进行场景显示和资源回收处理的。
///   1、前面三分之一:初始化.........
///   2、..............实际加载....... 
///   3、中间三分之一:假装在加载.....
///   4、后面三分之一:加载后资源处理...实际加载的时候,资源调入完毕时进度
///   
/// **************************************************************************  
/// 
/// </summary>
/// <param name="onValueChangedAction">加载进度变化时的回调方法</param>
/// <param name="sceneName">要加载的场景名字</param>
/// <param name="totalSliderTime">加载进度动画时间</param>
/// <param name="startAnim">开始加载的动画曲线</param>
/// <param name="midAnim">中间加载的动画曲线</param>
/// <param name="endAnim">加载后处理的动画曲线</param>
/// <returns></returns>
public static async UniTask LoadSceneAsyncWithSliderCurve(Action<float,string> onValueChangedAction,string sceneName,float totalSliderTime,AnimationCurve startAnim,AnimationCurve midAnim,AnimationCurve endAnim,CancellationToken ctk)
{       
    float progress = 0;          //每次循环的累计耗时
    float duration = 0;          //本次循环给定的用时
    float progressCurve = 0;     //曲线百分比进度 

    //第一段:
    Debug.Log("执行第一段");

    progress = 0.0f;
    duration = totalSliderTime / 3f;
    while (true)
    {            
        progress += Time.deltaTime;
        progressCurve = startAnim.Evaluate(progress / duration)/3f;
        onValueChangedAction?.Invoke(progressCurve,"开始加载...");         
        Debug.Log(progressCurve);
        if (progress > duration) break;
        await UniTask.Yield(ctk);
    }

    //第二段:
    //Debug.Log("执行第二段");

    //实际加载
    onValueChangedAction?.Invoke(progressCurve, "卖力加载...");
    await SceneManager.LoadSceneAsync(sceneName);
    
    //完毕后补加动画
    progress = 0.0f;
    duration = totalSliderTime / 3f;
    while (true)
    {
        progress += Time.deltaTime;
        progressCurve = 1f/3f + midAnim.Evaluate(progress / duration) / 3f;
        
        onValueChangedAction?.Invoke(progressCurve, "卖力加载...");          
        Debug.Log(progressCurve);
        if (progress > duration) break;
        await UniTask.Yield(ctk);
    }

    //第三段
    //Debug.Log("执行第三段");   
    progress = 0.0f;
    duration = totalSliderTime / 3f;
    while (true)
    {
        progress += Time.deltaTime;
        progressCurve = 2f/3f + endAnim.Evaluate(progress / duration) / 3f;
        onValueChangedAction?.Invoke(progressCurve, "继续加载...");         
        //Debug.Log(progressCurve);
        if (progress > duration) break;
        await UniTask.Yield(ctk);
    }

    onValueChangedAction?.Invoke(progressCurve, "加载完毕...");
}

六、测试

(1) 脚本挂载:

在这里插入图片描述

(2)测试的关键代码

点击按钮,显示进度条,加载中进度变化,加载完毕进度条隐藏

  //按钮逻辑——加载场景
  myButton.onClick.AddListener(async() => 
  {
      //显示进度UI
      mySlider.gameObject.SetActive(true);
      myText.gameObject.SetActive(true);
      await UniTask.DelayFrame(1, cancellationToken: this.GetCancellationTokenOnDestroy());

      //加载的过程
      await LoadSceneAsyncWithSliderCurve(actionOnValueChanged,sceneName, totalSliderTime,startAnim,midAnim,endAnim,this.GetCancellationTokenOnDestroy());

      //加载完毕隐藏进度的UI...
      await UniTask.Delay(500, cancellationToken: this.GetCancellationTokenOnDestroy());
      mySlider.gameObject.SetActive(false);
      myText.gameObject.SetActive(false);
  });

七、Code source附录

本文测试环境Editor,Unity2021.3.40,Win11

using UnityEngine;
using Cysharp.Threading.Tasks;//github-> UniTask包
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;
using System;
using System.Threading;
using UnityEditor;

/// <summary>
/// 场景跳转的进度条效果:
///     1、异步加载场景
///     2、进度条分成三段:初始阶段、加载阶段、回复场景阶段
///     3、各段滑动条的动画用【动画曲线】控制
/// </summary>
public class JumpScene : MonoBehaviour
{
    /// <summary>
    /// 【第一段进度条动画】的动画曲线
    /// </summary>
    [Header("【第一段进度条动画】的动画曲线")]
    public AnimationCurve startAnim;

    /// <summary>
    /// 【第二段进度条动画】的动画曲线
    /// </summary>
    [Header("【第二段进度条动画】的动画曲线")]
    public AnimationCurve midAnim;

    /// <summary>
    /// 【第三段进度条动画】的动画曲线
    /// </summary>
    [Header("【第三段进度条动画】的动画曲线")]
    public AnimationCurve endAnim;

    /// <summary>
    /// 跳转按钮
    /// </summary>
    [Header("跳转按钮")]
    public Button myButton;

    /// <summary>
    /// 要跳转的场景名字
    /// </summary>
    [Header("要跳转的场景名字")]
    public string sceneName;

    /// <summary>
    /// 进度比值显示框
    /// </summary>
    [Header("进度比值显示框")]
    public TMP_Text myText;

    /// <summary>
    /// 进度条
    /// </summary>
    [Header("进度条")]
    public Slider mySlider;

    /// <summary>
    /// 进度条给定的动画时间
    /// </summary>
    [Header("进度条给定的动画时间:三个动画阶段平分时间")]
    public float totalSliderTime = 2f;

    // Start is called before the first frame update
    void Start()
    {
        DontDestroyOnLoad(this);

        //加载进度变化的回调方法,进度值变化的时候调用
        //  value:进度条的值,从0-1
        //  tips:提示信息,加载中,努力加载中...加载完毕
        Action<float,string> actionOnValueChanged = (value,tips) => 
        {
            mySlider.value = value;                                //进度条更新
            myText.text = $"{tips} : {(int)(value * 100)}%";       //匹配的提示信息
            //Debug.Log($"加载进度为:{(int)(value * 100)}%"); 
        };
        
        //按钮逻辑——加载场景
        myButton.onClick.AddListener(async() => 
        {
            //显示进度UI
            mySlider.gameObject.SetActive(true);
            myText.gameObject.SetActive(true);
            await UniTask.DelayFrame(1, cancellationToken: this.GetCancellationTokenOnDestroy());

            //加载的过程
            await LoadSceneAsyncWithSliderCurve(actionOnValueChanged,sceneName, totalSliderTime,startAnim,midAnim,endAnim,this.GetCancellationTokenOnDestroy());

            //加载完毕隐藏进度的UI...
            await UniTask.Delay(500, cancellationToken: this.GetCancellationTokenOnDestroy());
            mySlider.gameObject.SetActive(false);
            myText.gameObject.SetActive(false);
        });
    }

    /// <summary>
    /// 场景跳转:异步加载一个场景,显示进度条,进度条滑动动画
    /// 
    /// **************************************************************************
    /// 大场景加载的时候,异步加载的进度值会卡死,因为update主线程卡死了
    /// (无论是协程还是用异步,都没有改观,都是卡死状态)。
    /// 出现该情况的时候,进度会卡住,直到加载完毕,进度值突然从【0%】调到【90%】,
    /// 90%代表资源加载完毕,余下10%的时间是用来进行场景显示和资源回收处理的。
    ///   1、前面三分之一:初始化.........
    ///   2、..............实际加载....... 
    ///   3、中间三分之一:假装在加载.....
    ///   4、后面三分之一:加载后资源处理...实际加载的时候,资源调入完毕时进度
    ///   
    /// **************************************************************************  
    /// 
    /// </summary>
    /// <param name="onValueChangedAction">加载进度变化时的回调方法</param>
    /// <param name="sceneName">要加载的场景名字</param>
    /// <param name="totalSliderTime">加载进度动画时间</param>
    /// <param name="startAnim">开始加载的动画曲线</param>
    /// <param name="midAnim">中间加载的动画曲线</param>
    /// <param name="endAnim">加载后处理的动画曲线</param>
    /// <returns></returns>
    public static async UniTask LoadSceneAsyncWithSliderCurve(Action<float,string> onValueChangedAction,string sceneName,float totalSliderTime,AnimationCurve startAnim,AnimationCurve midAnim,AnimationCurve endAnim,CancellationToken ctk)
    {       
        float progress = 0;          //每次循环的累计耗时
        float duration = 0;          //本次循环给定的用时
        float progressCurve = 0;     //曲线百分比进度 

        //第一段:
        Debug.Log("执行第一段");

        progress = 0.0f;
        duration = totalSliderTime / 3f;
        while (true)
        {            
            progress += Time.deltaTime;
            progressCurve = startAnim.Evaluate(progress / duration)/3f;
            onValueChangedAction?.Invoke(progressCurve,"开始加载...");         
            Debug.Log(progressCurve);
            if (progress > duration) break;
            await UniTask.Yield(ctk);
        }

        //第二段:
        //Debug.Log("执行第二段");

        //实际加载
        onValueChangedAction?.Invoke(progressCurve, "卖力加载...");
        await SceneManager.LoadSceneAsync(sceneName);
        
        //完毕后补加动画
        progress = 0.0f;
        duration = totalSliderTime / 3f;
        while (true)
        {
            progress += Time.deltaTime;
            progressCurve = 1f/3f + midAnim.Evaluate(progress / duration) / 3f;
            
            onValueChangedAction?.Invoke(progressCurve, "卖力加载...");          
            Debug.Log(progressCurve);
            if (progress > duration) break;
            await UniTask.Yield(ctk);
        }

        //第三段
        //Debug.Log("执行第三段");   
        progress = 0.0f;
        duration = totalSliderTime / 3f;
        while (true)
        {
            progress += Time.deltaTime;
            progressCurve = 2f/3f + endAnim.Evaluate(progress / duration) / 3f;
            onValueChangedAction?.Invoke(progressCurve, "继续加载...");         
            //Debug.Log(progressCurve);
            if (progress > duration) break;
            await UniTask.Yield(ctk);
        }

        onValueChangedAction?.Invoke(progressCurve, "加载完毕...");
    }

    public async UniTask LoadTest1()
    {
        //定义加载任务
        AsyncOperation loadTask = SceneManager.LoadSceneAsync("SceneName");
        loadTask.allowSceneActivation = false;   //加载完毕场景不立即显示

        await loadTask;                          //实际加载过程

        //此处,用户要进行其他操作,比如点击一个按钮,把数据上传到服务器
        //...

        loadTask.allowSceneActivation = true;    //设置成true后,系统开始后续的10%的工作,会把新场景显示,把老场景卸载
    }

    public async UniTask LoadTest2()
    {
        //定义加载任务
        AsyncOperation loadTask = SceneManager.LoadSceneAsync("茶树叶片形态观察", LoadSceneMode.Additive);

        //SceneManager.SetActiveScene(SceneManager.GetSceneByName("新加入的场景名字"));

        //loadTask.allowSceneActivation = false;   //加载完毕场景不立即显示,处于隐藏状态

        await loadTask;                          //实际加载过程

        //await UniTask.Delay(1000);               //等待1秒     
        //loadTask.allowSceneActivation = true;    //把新场景显示出来
    }

    [ContextMenu("Additive加载模式测试")]
    void test2()
    {
        LoadTest2().Forget();
    }

    void test()
    {
        var myScene = SceneManager.GetSceneByName("场景名字");
        SceneManager.SetActiveScene(myScene);
    }

    public async UniTask test3()
    {
        // 定义进度报告器
        var progress = new Progress<float>(value =>
        {     
            //更新滑动条进度
            Debug.Log($"加载进度: {value * 100}%");
        });

        //实际加载
        await SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Single).ToUniTask(progress: progress);      
    }

    public async UniTask test4()
    {
        var progress = 0.0f;         //当前累计耗时
        var duration = 3f;           //给定的动画时间,3秒
        var progressCurve = 0f;      //曲线进度,按照曲线速度运动,而不是匀速运动
        while (true)
        {
            progress += Time.deltaTime;
            progressCurve = startAnim.Evaluate(progress / duration) / duration;            
            Debug.Log(progressCurve);
            if (progress > duration) break;
            await UniTask.Yield();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

James Forshaw的.NET Remoting反序列化升级版之TypeFilterLevel.Low模式无文件payload任意代码执行

引用 这篇文章的目的是介绍一款基于James Forshaw的.NET Remoting反序列化工具升级版在TcpServerChannel的TypeFilterLevel.Low模式无文件payload任意代码执行poc的开发心得 文章目录 引用简介.NET Remoting的应用程序通道介绍.NET Remoting的应用程序利用场景介绍扩展ysoseria…

【卫星影像地图API】常见地图服务_WMS_WFS_WCS_ WMTS

地图服务作为一种展现数据集的良好方式&#xff0c;为地理信息的共享起到重要作用。本文将介绍常见地图服务的相关内容。 网络地图服务&#xff08;WMS&#xff09; &#xff08;1&#xff09;概念 网络地图服务 (Web Map Service&#xff0c;WMS)指从地理信息动态产生具有地…

Docker最佳实践进阶(二):Docker Compose容器编排

大家好&#xff0c;在上篇文章中博主演示了Dockerfile常用的命令&#xff0c;以及如何利用Dockerfile构建镜像&#xff0c;生成容器服务&#xff0c;但是在实际应用环境中&#xff0c;特别是在微服务架构中&#xff0c;一个应用系统可能包含多个微服务&#xff0c;每个微服务可…

遇到的基本问题

遇到的基本问题 Linux常用操作 1、关闭防火墙、配置本地yum源、添加静态网卡 systemctl stop firewalld if [ getenforce "Enforcing" ];thensetenforce 0 fi sleep 3 echo "防火墙和selinux高级权限管理已关闭" ############ #添加静态网卡 #########…

配置访问权限|预防数据泄漏

IT行业正在以闪电般速度发展&#xff0c;而网络攻击也随之激增。在今年4月份的IT数据泄漏报告中&#xff0c;教育行业数据泄漏事件数量最多&#xff0c;其次是医疗保健行业、IT服务和软件行业。 为什么有许多数据泄漏事件&#xff1f; 通常是由于缺乏访问权限的认证&#xff0…

渗透实战——为喜欢的游戏“排忧解难”

本文仅用于技术研究学习&#xff0c;请遵守相关法律&#xff0c;禁止使用本文所提及的相关技术开展非法攻击行为&#xff0c;由于传播、利用本文所提供的信息而造成任何不良后果及损失&#xff0c;与本账号及作者无关。 资料查询来源- 安全社区与AI模型结合探索【文末申请免费…

了解数据库中常用存储引擎数据结构(4)

目录 深入了解LSM树及其发展 一条数据的整体写入过程 读操作&#xff08;Bloom Filter优化&#xff09; 合并策略&#xff08;Merging Policy&#xff09; LSM-Tree并发控制机制 一些Compaction优化方案 深入了解LSM树及其发展 LSM Tree 的概念起源于 1996年的论文《The…

【网络工程师模拟面试题】(2)OSPF区域划分与LSA细节

一、OSPF中心结点与周围200个路由器节点建立邻居&#xff0c;该如何划分区域&#xff0c;为什么&#xff1f; 这个问题其实没有标准答案&#xff0c;因为据OSPF RFC标准文档(RFC 2328 OSPF Version 2)来看&#xff0c;其中内容并没有规定OSPF单区域的邻居数量限制&#xff0c;…

【鸿蒙学习】HarmonyOS应用开发者基础 - 从网络获取数据

学完时间&#xff1a;2024年8月15日 一、前言叨叨 学习HarmonyOS的第七课&#xff0c;人数居然反超到了3735名了&#xff0c;难道前面的那一课&#xff0c;这么多人挂科了吗。不过这一节的内容稍微简单一些&#xff0c;都是网络相关知识。 <HarmonyOS第一课>从网络获取…

【Angular18】封装自定义组件

1. 准备组件 2. 创建打包文件夹及部分配置文件 创建 文件夹app-legalentities-root拷贝组件源文件到新的文件夹app-legalentities中创建文件 .npmrc registry发布地址always-authtrue创建文件 ng-package.json {"$schema": "./node_modules/ng-packagr/ng-pac…

FChen的408学习日记--三次握手和四次握手

一、三次握手 在建立连接的过程中&#xff0c;首先SYN1&#xff0c;随机发送sqex。服务器接受后要反过来对客户端发送连接请求&#xff0c;SYN1&#xff0c;随机发送sqey&#xff0c;ackx1。然后客户端还要发送连接确认报文&#xff0c;原因如下 例题&#xff1a; 二、四次…

WeiXin Bill Record

WeiXin Bill Record 微信账单记录查询流程 【我】 【钱包】 【账单】 选中一笔【查询对象】的交易记录 【查看往来转账】 【导出凭证】 选择查询开始时间&#xff0c;结束时间&#xff1b;【申请】 【验证】 【同意】协议 进入人脸识别 【申请】 【查看详情】 【确定】

SaaS中如何应用AIGC:智能赋能,引领未来

引言 在数字化浪潮的推动下&#xff0c;SaaS&#xff08;软件即服务&#xff09;已成为企业数字化转型的重要工具。而 AIGC 作为人工智能领域的前沿技术&#xff0c;正逐步渗透到SaaS的各个环节&#xff0c;为企业带来前所未有的智能化体验。 一、智能客服与自动化服务 在Saa…

Docker-命令

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Docker架构二、Docker进程相关命令&#xff08;一&#xff09;启动 docker 服务&#xff08;二&#xff09;重启 docker 服务&#xff08;三&#xff09;停…

C语言——二分法求有序数组中指定元素的位置

二分法只是用于有序的数组&#xff0c;如果是无序输入&#xff0c;还需要进行排序。此外&#xff0c;mid 中间值不是整数&#xff0c;要取整。 #include <stdio.h> #include <stdlib.h> int Bin_search(int* p, int len, int target) { int left 0; int …

数实融合打破场景边界,苏宁大店直播火了!

今年以来&#xff0c;促消费扩内需举措持续发力&#xff0c;创新消费场景作为重点发力方向&#xff0c;在多个场合被提及。近期&#xff0c;国务院《关于促进服务消费高质量发展的意见》进一步提出&#xff0c;加速推动消费场景应用升级和数字赋能&#xff0c;构建智慧商圈、智…

苹果iOS 17.6.1正式推送,有哪些机型值得更新呢?

在科技界&#xff0c;每一次操作系统更新都备受瞩目&#xff0c;尤其是对于苹果这样在全球范围内拥有庞大用户群的品牌而言。 最近&#xff0c;苹果发布了iOS 17.6.1更新&#xff0c;这一小版本更新不仅修复了一系列关键错误&#xff0c;还针对之前版本中存在的问题进行了针对…

纺织设备如何实现信息化转型?

纺织设备的信息化转型&#xff0c;是当代制造业智能化升级的关键一环&#xff0c;它不仅深刻影响着纺织行业的生产效率与产品质量&#xff0c;还促进了整个产业链的创新与优化。这一进程不仅仅是简单地将信息技术融入传统纺织机械中&#xff0c;而是通过深度融合物联网、大数据…

【AI】AI编程工具概述

1. AI编程工具概述 1.1 定义与功能 AI编程工具是利用人工智能技术辅助编程工作的软件集合&#xff0c;它们通过集成到现有的开发环境中&#xff0c;提供代码自动生成、补全、错误检测、优化建议等功能&#xff0c;旨在提高开发效率和代码质量。 代码生成&#xff1a;AI工具可…

[书生大模型实战营][L0][Task1] Linux 远程连接 InternStudio

[书生大模型实战营][Task1] Linux 远程连接 InterStudio 1. 申请 InterStudio 账号 https://studio.intern-ai.org.cn/console/dashboard 2. ssh 生成公匙与密匙 使用 ssh-gen 生成公匙与密匙 # 1. ssh-gen ssh-gen# 2. 查看生成的文件 ls ~/.ssh# 3. 打开生成的公匙&#…