GameFrameWork框架(Unity3D)使用笔记(八) 实现场景加载进度条

news2024/10/5 15:29:23

前言:

        游戏在转换场景的时候,需要花费时间来加载相关的资源。而这个过程往往因为游戏场景的规模和复杂度以及玩家电脑配置的原因花费一小段时间(虽然这个项目里用不到)。

        所以,如果这一小段时间,画面就卡在这里,啥也做不了,玩家也不知道啥时候能加载好。这个等待的时间实际上非常地影响玩家的使用体验。

        目前大多数游戏在转换关卡这种时候都会有个加载界面,显示加载进度。这样玩家可以对啥时候能加载好有个心理预估(判断要不要因为加载太久浪费时间不如卸载游戏(开个玩笑))。

        一般加载场景显示进度条的方法搜搜就有了,就是利用Unity自带的异步加载函数SceneManager.LoadSceneAsync()加载场景,并且通过AsyncOperation跟踪加载进度,从而设置进度条之类的。

        不过,在GameFramework框架下,加载场景的模块被进一步封装,那怎么在UGF下实现加载的进度条就是本篇的主要内容。


一、实现过程讲解

        我看过一些非GF的加载场景的方案,大多数都是:对于从场景a-->场景b的过程,将其变为从场景a-->场景c-->场景b

        其中,场景c里面主要就只有一个加载界面,主要用来显示进度条等内容。这样的话,从a->c可以非常快速地跳转(因为c中就只有个UI所以即便配置不高也能很快跳转)然后玩家在c中观看进度条的时候,后台异步加载场景b,加载完毕后立刻转到场景b。

        但是,在GF框架下,有个不同的地方。就是GF框架预制体所在的Launcher场景是一直存在的,并且框架的UI统一在这个场景里管理。

        所以在GF里实现进度条的功能,我的方案是直接在ProcedureChangeScene流程里面加载新场景的同时显示进度条UI,并且在加载完成后关闭UI。

        此外,由于一些原因(参考这一篇:http://t.csdn.cn/65FDe),想要测试这个进度条的真正效果,需要把当前工程Build再运行测试。


一、拼制UI

 在场景里面拼个进度条UI:

然后写UI的逻辑脚本,这里实现控制UI进度条的函数方便之后调用:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace ShadowU
{
    public class LoadingForm: UGuiForm
    {
        public GameObject mask;     //进度条的遮罩
        public Text loadingText;    //加载中的文字

        protected override void OnClose(bool isShutdown, object userData)
        {
            base.OnClose(isShutdown, userData);
        }

        protected override void OnInit(object userData)
        {
            base.OnInit(userData);
        }

        protected override void OnOpen(object userData)
        {
            base.OnOpen(userData);
            loadingText.text = "加载中.  .  .  .  .  .  ";
        }

        protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(elapseSeconds, realElapseSeconds);
            //控制加载中文字后的句号浮动
            string temp = loadingText.text;
            temp.Insert(3, temp[temp.Length - 1].ToString()).Remove(temp.Length - 1);
            loadingText.text = temp;
        }
        void SetProcess(float a)
        {
            a = Mathf.Clamp(a,0f,1.0f);//将数值控制在0-1
            mask.transform.SetLocalScaleX(a);
        }
    }
}

接上脚本,设置好public参数,做成预制体:


二、修改ProcedureChangeScene流程代码

         ProcedureChangeScene开始的时候,加载出Loading界面,同时开始异步加载新场景。

        通过LoadSceneUpdateEvent事件来更新加载界面进度条的进度。

        最后,在场景加载完成后关闭Loading界面即可。

        新的ProcedureChangeScene代码如下:


using GameFramework.Fsm;
using GameFramework.Event;
using GameFramework.DataTable;
using UnityGameFramework.Runtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;

namespace ShadowU
{
    public class ProcedureChangeScene : ProcedureBase
    {
        private const int MenuSceneId = 1;   //菜单场景的ID 

        private bool m_ChangeToMenu = false; //是否转换为菜单
        private bool m_IsChangeSceneComplete = false; //转换场景是否结束

        private LoadingForm m_LoadingForm;    //加载界面
        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnEnter(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner)
        {
            base.OnEnter(procedureOwner);

            Debug.Log("ChangeScene!");
            m_IsChangeSceneComplete = false; //如果为true的话 则在update中会切换流程

            //打开加载界面
            GameEntry.UI.OpenUIForm(AssetUtility.GetUIFormAsset("LoadingForm"), "Default", 1, this);

            //注册事件
            GameEntry.Event.Subscribe(LoadSceneSuccessEventArgs.EventId,OnLoadSceneSuccess);
            GameEntry.Event.Subscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Subscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Subscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);
            GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId,OnOpenUIFormSuccess);

            //隐藏所有实体
            GameEntry.Entity.HideAllLoadingEntities();
            GameEntry.Entity.HideAllLoadedEntities();

            //卸载所有场景
            string[] loadedSceneAssetNames = GameEntry.Scene.GetLoadedSceneAssetNames();

            foreach (string sn in loadedSceneAssetNames)
                GameEntry.Scene.UnloadScene(sn);

            //还原游戏速度
            GameEntry.Base.ResetNormalGameSpeed();

            
            //获取下一个场景的ID
            int sceneId = procedureOwner.GetData<VarInt32>("NextSceneId");
            m_ChangeToMenu = sceneId == MenuSceneId; //判断是否是转到菜单
            IDataTable<DRScene> dtScene = GameEntry.DataTable.GetDataTable<DRScene>();
            DRScene drScene = dtScene.GetDataRow(sceneId); //获取数据表行
            if(drScene == null)
            {
                Log.Warning("Can not load scene '{0}' from data table.", sceneId.ToString());
                return;
            }
            GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName),Constant.AssetPriority.SceneAsset,this);
        }



        protected override void OnLeave(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);

            GameEntry.Event.Unsubscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
            GameEntry.Event.Unsubscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Unsubscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Unsubscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);
            GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId,OnOpenUIFormSuccess);

            //关闭UI
            if (m_LoadingForm != null)
            {
                m_LoadingForm.Close(isShutdown);
                m_LoadingForm = null;
            }
        }

        protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);


            if (!m_IsChangeSceneComplete)   
            {
                return;  //还没完成场景切换
            }

            if (m_ChangeToMenu)
            {
                ChangeState<ProcedureMenu>(procedureOwner);   //菜单
            }else
            {
                ChangeState<ProcedureMain>(procedureOwner);   //游戏运行流程
            }
        }
        
        private void OnLoadSceneSuccess(object sender,GameEventArgs e)
        {
            LoadSceneSuccessEventArgs ne = (LoadSceneSuccessEventArgs)e;
            if(ne.UserData != this)
            {
                return;
            }
            Log.Info("Load scene '{0}' OK.", ne.SceneAssetName);
            m_IsChangeSceneComplete = true;
        }
        private void OnLoadSceneFailure(object sender, GameEventArgs e)
        {
            LoadSceneFailureEventArgs ne = (LoadSceneFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Load scene '{0}' failure, error message '{1}'.", ne.SceneAssetName, ne.ErrorMessage);
        }

        private void OnLoadSceneUpdate(object sender, GameEventArgs e)
        {
            LoadSceneUpdateEventArgs ne = (LoadSceneUpdateEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' update, progress '{1}'.", ne.SceneAssetName, ne.Progress.ToString("P2"));
            //更新加载界面的进度条
            if(m_LoadingForm != null)
                m_LoadingForm.SetProcess(ne.Progress);
        }

        private void OnLoadSceneDependencyAsset(object sender, GameEventArgs e)
        {
            LoadSceneDependencyAssetEventArgs ne = (LoadSceneDependencyAssetEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' dependency asset '{1}', count '{2}/{3}'.", ne.SceneAssetName, ne.DependencyAssetName, ne.LoadedCount.ToString(), ne.TotalCount.ToString());
        }
        private void OnOpenUIFormSuccess(object sender, GameEventArgs e)
        {
            OpenUIFormSuccessEventArgs ne = (OpenUIFormSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadingForm = (LoadingForm)ne.UIForm.Logic;
        }
    }
}

 三、测试效果

        直接编辑器模式运行的话看场景加载并不是异步的,所以要测试这个进度条的真正效果需要打包运行。

        关于打包的过程之后的文章里会讲,这里就先跳过了。

        测试:

 进度条的功能是完成了!

但是。。。又出了新的问题:菜单界面在加载界面之上。

不过编辑器模式运行并没有这个问题:

    

但是没有问题只是看上去的。。。如果我立即暂停后观察,其实这个模式下也会两个UI同屏,只不过相对来说时间比较短暂。我经过一段时间分析后,想到UGuiForm里面在关闭和打开界面的时候都有淡入淡出的逻辑,于是作出如下假设:

加载界面看到菜单界面并不是渲染层级先后的问题,而是它们都在淡入或淡出过程中。所以说,他们都处于半透明状态所以能都看得见。

(因为基于这个假设能解决问题那我就不去证明我这个假设到底对不对了嘿嘿~) 

那解决办法就很灵活了。比如可以判断取消打开加载界面的淡入效果。不过我觉得这样改结构会很不美观。

于是我打算这样处理:让加载界面至少停留一秒。同时减小淡入淡出的时间。

在UGuiForm.cs里面修改淡入淡出时间

修改一下ProcedureChangeScene的代码(增加了和loadingTimer变量有关的部分):


using GameFramework.Fsm;
using GameFramework.Event;
using GameFramework.DataTable;
using UnityGameFramework.Runtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;

namespace ShadowU
{
    public class ProcedureChangeScene : ProcedureBase
    {
        private const int MenuSceneId = 1;   //菜单场景的ID 

        private bool m_ChangeToMenu = false; //是否转换为菜单
        private bool m_IsChangeSceneComplete = false; //转换场景是否结束

        private LoadingForm m_LoadingForm;    //加载界面
        private float loadingTimer;           //加载界面停留的计时器
        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnEnter(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner)
        {
            base.OnEnter(procedureOwner);

            Debug.Log("ChangeScene!");
            m_IsChangeSceneComplete = false; //如果为true的话 则在update中会切换流程

            //打开加载界面
            GameEntry.UI.OpenUIForm(AssetUtility.GetUIFormAsset("LoadingForm"), "Default", 1, this);
            loadingTimer = 1.0f;         //加载界面至少停留一秒

            //注册事件
            GameEntry.Event.Subscribe(LoadSceneSuccessEventArgs.EventId,OnLoadSceneSuccess);
            GameEntry.Event.Subscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Subscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Subscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);
            GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId,OnOpenUIFormSuccess);

            //隐藏所有实体
            GameEntry.Entity.HideAllLoadingEntities();
            GameEntry.Entity.HideAllLoadedEntities();

            //卸载所有场景
            string[] loadedSceneAssetNames = GameEntry.Scene.GetLoadedSceneAssetNames();

            foreach (string sn in loadedSceneAssetNames)
                GameEntry.Scene.UnloadScene(sn);

            //还原游戏速度
            GameEntry.Base.ResetNormalGameSpeed();

            
            //获取下一个场景的ID
            int sceneId = procedureOwner.GetData<VarInt32>("NextSceneId");
            m_ChangeToMenu = sceneId == MenuSceneId; //判断是否是转到菜单
            IDataTable<DRScene> dtScene = GameEntry.DataTable.GetDataTable<DRScene>();
            DRScene drScene = dtScene.GetDataRow(sceneId); //获取数据表行
            if(drScene == null)
            {
                Log.Warning("Can not load scene '{0}' from data table.", sceneId.ToString());
                return;
            }
            GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName),Constant.AssetPriority.SceneAsset,this);
        }



        protected override void OnLeave(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);

            GameEntry.Event.Unsubscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
            GameEntry.Event.Unsubscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Unsubscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Unsubscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);
            GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId,OnOpenUIFormSuccess);

            //关闭UI
            if (m_LoadingForm != null)
            {
                m_LoadingForm.Close(isShutdown);
                m_LoadingForm = null;
            }
        }

        protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);


            if (!m_IsChangeSceneComplete)   
            {
                return;  //还没完成场景切换
            }

            m_LoadingForm.SetProcess(1);

            if(loadingTimer > 0)  
            {
                loadingTimer -= elapseSeconds;//更新计时器
                return;
            }

            if (m_ChangeToMenu)
            {
                ChangeState<ProcedureMenu>(procedureOwner);   //菜单
            }else
            {
                ChangeState<ProcedureMain>(procedureOwner);   //游戏运行流程
            }
        }
        
        private void OnLoadSceneSuccess(object sender,GameEventArgs e)
        {
            LoadSceneSuccessEventArgs ne = (LoadSceneSuccessEventArgs)e;
            if(ne.UserData != this)
            {
                return;
            }
            Log.Info("Load scene '{0}' OK.", ne.SceneAssetName);
            m_IsChangeSceneComplete = true;
        }
        private void OnLoadSceneFailure(object sender, GameEventArgs e)
        {
            LoadSceneFailureEventArgs ne = (LoadSceneFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Load scene '{0}' failure, error message '{1}'.", ne.SceneAssetName, ne.ErrorMessage);
        }

        private void OnLoadSceneUpdate(object sender, GameEventArgs e)
        {
            LoadSceneUpdateEventArgs ne = (LoadSceneUpdateEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' update, progress '{1}'.", ne.SceneAssetName, ne.Progress.ToString("P2"));
            //更新加载界面的进度条
            if(m_LoadingForm != null)
                m_LoadingForm.SetProcess(ne.Progress);
        }

        private void OnLoadSceneDependencyAsset(object sender, GameEventArgs e)
        {
            LoadSceneDependencyAssetEventArgs ne = (LoadSceneDependencyAssetEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' dependency asset '{1}', count '{2}/{3}'.", ne.SceneAssetName, ne.DependencyAssetName, ne.LoadedCount.ToString(), ne.TotalCount.ToString());
        }
        private void OnOpenUIFormSuccess(object sender, GameEventArgs e)
        {
            OpenUIFormSuccessEventArgs ne = (OpenUIFormSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadingForm = (LoadingForm)ne.UIForm.Logic;
        }
    }
}

此外还有个细节:就是进度条到90就不动了。其实场景加载到90%的时候就已经加载完了,最后的10%就在于有没有把场景显示出来。那为了看起来不膈应,我上面的代码里在加载完场景后手动把进度条设置为100:

打包看下最终效果:

 效果挺理想的,那就这样了!

        

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

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

相关文章

计算机网络 —— TCP篇 三次握手与四次挥手

计算机网络系列文章目录 TCP篇 三次握手四次挥手 socket 文章目录计算机网络系列文章目录前言4.1 tcp三次握手与四次挥手面试题4.1.1 TCP的基本认识TCP头部为什么需要tcp&#xff0c;tcp工作在哪一层什么是tcp什么是tcp连接如何唯一确定一个tcp连接(tcp&udp比较) UDP 和 T…

机器学习【西瓜书/南瓜书】--- 第1章绪论+第二章模型选择和评估(学习笔记+公式推导)

【西瓜书南瓜书】task01: 第1、2章&#xff08;2天&#xff09; 第一章 绪论 主要符号表 下述这些符号在本书中将频繁的使用&#xff0c;务必牢记于心各个特殊符号所具有的的含义 &#x1f31f;对上述部分定义做一下解释&#xff1a; 向量有维度&#xff0c;其中的元素是有…

路由器NAT典型配置

1.组网需求内部网络中IP地址为10.110.10.0/24的用户可以访问Internet&#xff0c;其它网段的用户则不能访问Internet。外部的PC可以访问内部的服务器。公司具有202.38.160.100/24至202.38.160.105/24六个合法的IP地址。选用202.38.160.100作为公司对外的IP地址&#xff0c;WWW服…

stm32平衡小车(2)-----编码器电机驱动

前言&#xff1a;之前做arduino小车的时候使用的是L298N电机&#xff0c;没有用过编码器&#xff0c;这次第一次用编码器&#xff0c;还是比较懵圈&#xff0c;记录一下学的整个过程。 1.编码器的简介 霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字…

下载整个网站

使用Cyotek WebCopy下载整个网站一、下载网站复制所需软件&#xff1a;二、打开Cyotek WebCopy&#xff0c;然后下载网站系统环境&#xff1a;win10 所需工具&#xff1a;Cyotek WebCopy 一、下载网站复制所需软件&#xff1a; https://www.cyotek.com/cyotek-webcopy/downloa…

3-3存储系统-高速缓冲存储器Cache

文章目录一.概述二.Cache与主存的映射方式1.直接映射2.全相联映射3.组相联映射三.Cache中主存块的替换算法1.随机算法RAND2.先进先出算法FIFO3.最近最少使用算法LRU4.最不经常使用算法LFU四.Cache写策略1.写命中2.写不命中一.概述 高速缓冲存储器&#xff08;Cache&#xff09…

labelme使用labelme2voc.py忽略部分标签生成VOC/coco类型数据集(Ignore a label in json file)

一&#xff1a;背景和问题描述这是一个比较小众&#xff0c;且查找全网未有答案的问题。在使用labelme标注数据之后&#xff0c;生成了json文件。在利用json文件生成可用于训练分割模型的voc或者coco数据集时&#xff0c;可以使用labelme中自带的示例文件labelme2voc.py&#x…

第二章.线性回归以及非线性回归—弹性网

第二章.线性回归以及非线性回归 2.14 弹性网&#xff08;Elastic Net&#xff09; Elastic Net是一种使用L1和L2作为正则化矩阵的线性回归模型&#xff0c;这种组合用于只有很少的权重非零的稀疏模型。 当多个特征和另一个特征相关时&#xff0c;弹性网络非常有用&#xff0c;L…

C++ STL简介

文章目录前言一、STL概述二、STL历史三、STL六大组件功能与运用前言 对C/C学习感兴趣的可以看看这篇文章哦&#xff1a;C/C教程 一、STL概述 在软件行业&#xff0c;一直都希望建立一种可以重复运用的东西和一种可以制造出“可重复使用的东西”的方法&#xff0c;来让程序员…

什么是基于模型设计(MBD)?

MBD(Model based Design)是什么&#xff1f; 随着嵌入式行业的快速发展&#xff0c;MBD作为解决专家紧缺、国内解决方案匮乏的新软件开发方式备受关注。 MBD是一种通过建模自动生成代码的&#xff08;Auto-generation Code&#xff09;开发方式。 可以说它与如何用传统的C/C等计…

CANoe-仿真总线上的红蓝线、“CANoe DEMO“ license下的软件限制

1、仿真总线上的红蓝线 最近有人问我一个问题,就是Simulation Setup界面下的仿真网络里,有两条线:红线、蓝线。它们表示什么意思呢? 有人可能首先想到:会不会是代表CAN总线的两条物理连线? 那LIN网络呢?LIN网络属于单条线,它在仿真网络里应该显示一条线咯? LIN总线也…

ThreadLocal 详解

ThreadLocal 详解 1. ThreadLocal简介 1.1 官方介绍 /*** This class provides thread-local variables. These variables differ from* their normal counterparts in that each thread that accesses one (via its* {code get} or {code set} method) has its own, indep…

【go语言http2.0代码实现】

go语言之http2.0Serverclient之前主要说的是基于http1.1的。然后因为http1.1存在的局限性&#xff0c;现在http2.0越来越流行&#xff0c;这里来根据go的源码来分析一下http2.0的实现。首先需要注意的是http2.0是在https的基础之上&#xff0c;因此推荐有https的基础或者看前面…

如何在Microsoft Teams中发布作业

之前我们介绍了在Microsoft Teams中收发批改作业的基础使用方法。今天我们会在“发布作业”这个方面上进行详细介绍。 首先我们进入Teams的“作业”点击“创建”。 选择“作业”。 可以通过“附加”的形式发布已创建的作业文件。 可以通过选择OneDrive的形式来选取里面的文件发…

BOSS直聘依然面临监管和估值过高的风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 BOSS直聘是中国重新开放和经济复苏的受益者 由于中国已经全面放开&#xff0c;所以&#xff0c;全球各地的分析师们正在上调对中国2023年经济增长的预测。 比如CNBC的文章就提到摩根士丹利&#xff08;MS&#xff09;的经…

Pandas 数据结构 - Series

前言Pandas Series 类似表格中的一个列&#xff08;column&#xff09;&#xff0c;类似于一维数组&#xff0c;可以保存任何数据类型。Series 由索引&#xff08;index&#xff09;和列组成&#xff0c;函数如下&#xff1a;pandas.Series( data, index, dtype, name, copy)参…

基于springboot,vue电影院售票系统

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

Java 线程的几种状态及其切换的条件

1.线程状态及其含义2.状态之间切换的条件1.线程状态及其含义 NEW(初始化): 表示创建了Thread对象,但是还没有调用start (也就是系统内核还是没有创建对应的PCB) RUNNABLE(运行): 表示可运行的.线程创建后,调用了start方法,等待CPU的调度或者正在CPU中运行. BLOCKED(阻塞): 表…

【白皮书】PROFIBUS网络诊断

PROFIBUS标准已有30多年的历史&#xff0c;如今已是一种成熟的数字现场总线技术。PROFIBUS通常用于工厂和过程自动化行业&#xff0c;也可用于食品、饮料或制药等混合行业。此外&#xff0c;其还适用于楼宇自动化和轨道交通等领域。可见&#xff0c;PROFIBUS是一种可服务于这些…

华为OD机试 - 信号发射和接收

题目描述 有一个二维的天线矩阵,每根天线可以向其他天线发射信号,也能接收其他天线的信号,为了简化起见,我们约定每根天线只能向东和向南发射信号,换言之,每根天线只能接收东向或南向的信号。 每根天线有自己的高度anth,每根天线的高度存储在一个二维数组中,各个天线…