当前位置: 首页 > article >正文

unity学习24:场景scene相关生成,加载,卸载,加载进度,异步加载场景等

目录

1 场景数量 SceneManager.sceneCount

2 直接代码生成新场景 SceneManager.CreateScene

3 场景的加载

3.1 用代码加载场景,仍然build setting里先加入配置

3.2 卸载场景 SceneManager.UnloadSceneAsync();

3.3 同步加载场景 SceneManager.LoadScene

3.3.1  两种加载方式

3.4 异步加载场景

3.5 测试代码

3.5.1 有问题的测试代码

(代码创建的新Scene 需要手动去build Setting添加?)

3.6 场景的叠加效果

4 同步和异步

4.1  同步和异步

4.2 多线程  协程

4.2.1 多线程

4.2.2 协程

4.3 异步加载场景UnityEngine.SceneManagement;

4.3.1 除了默认的,还需要额外导入其他包

4.3.2  测试异步跳转场景,可成功

4.3.3 详细代码和注释

4.3.4 注释内容

5 加载进度

5.1  对应的协程的进度  operation1.progress

5.2  关于进度的数值

5.3 对应代码

5.4 如何做个显示的UI进度条

6 按条件跳转新地图

6.1 延迟跳转

6.2 测试代码


1 场景数量 SceneManager.sceneCount

  • //统计已经加载的场景数量
  • Debug.Log(SceneManager.sceneCount);

2 直接代码生成新场景 SceneManager.CreateScene

  • // 代码里可以创建新场景:直接用代码
  • Scene scene3=SceneManager.CreateScene("Scene3");

3 场景的加载

3.1 用代码加载场景,仍然build setting里先加入配置

  • 也是要注意,新场景的加载模式
  • 用代码创建的Scene也可以现在build setting里先加入配置

Scene 'Scene3' couldn't be loaded because it has not been added to the build settings or the AssetBundle has not been loaded.
To add a scene to the build settings use the menu File->Build Settings...
UnityEngine.SceneManagement.SceneManager:LoadScene (string)
SceneTest:Start () (at Assets/SceneTest.cs:43)

3.2 卸载场景 SceneManager.UnloadSceneAsync();

  • 卸载场景
  • SceneManager.UnloadSceneAsync("Scene3");

3.3 同步加载场景 SceneManager.LoadScene

  • //同步加载场景,卡顿,等待
  • SceneManager.LoadScene("Scene3");
  • SceneManager.loadScene("scene3",LoadSceneMode.Single);
  • SceneManager.loadScene("scene3",LoadSceneMode.Additive);

3.3.1  两种加载方式

只加载1个,替换之前的Scene

  • SceneManager.LoadScene("Scene2")  
  • 默认方式是 LoadSceneMode.Single
  • SceneManager.LoadScene("Scene2",LoadSceneMode.Single)  

新的场景加载,老的也在,相当于同时都加载生效

  • SceneManager.LoadScene("Scene2",LoadSceneMode.Additive) 

3.4 异步加载场景

  • //异步加载场景
  • //SceneManager.loadSceneAsync("scene3");

3.5 测试代码

3.5.1 有问题的测试代码

(代码创建的新Scene 需要手动去build Setting添加?)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        ///先查看当前Scene
        //获取当前场景
        Scene scene1=SceneManager.GetActiveScene();

        //场景名称
        Debug.Log(scene1.name);

         //场景路径
        Debug.Log(scene1.path);      
    
        //场景索引
        Debug.Log(scene1.buildIndex);   
        GameObject[] gb1=scene1.GetRootGameObjects();
        Debug.Log(gb1.Length);

        //跳转场景
        //SceneManager.LoadScene(2);
        //SceneManager.LoadScene("Scene2");

        //调用异步的Start1
        Start1();

        //统计已经加载的场景数量
        Debug.Log(SceneManager.sceneCount);

        //创建新场景:直接用代码
        Scene scene3=SceneManager.CreateScene("Scene3");

        //卸载场景
        //SceneManager.UnloadSceneAsync("Scene3");

        //同步加载场景,卡顿,等待
        SceneManager.LoadScene("Scene3");
        //SceneManager.loadScene("scene3",LoadSceneMode.Single);
        //SceneManager.loadScene("scene3",LoadSceneMode.Additive);

        //异步加载场景
        //SceneManager.loadSceneAsync("scene3");


    }

        async void Start1()
        {
            AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(2);
            // 等待场景加载完成
            while (!asyncLoad.isDone)
            {
                await System.Threading.Tasks.Task.Yield();
            }
            // 场景加载完成后获取信息
            Debug.Log(SceneManager.GetActiveScene().name);

            //获取当前场景
            //新定义1个scene2  Scene scene2=
            Scene scene2=SceneManager.GetActiveScene();

            //场景是否已经加载, 但是可能还没有激活新的Scene
            Debug.Log(scene2.isLoaded); 

            ///再次查看当前Scene
            //场景名称
            Debug.Log(scene2.name);

            //场景路径
            Debug.Log(scene2.path);      
        
            //场景索引
            Debug.Log(scene2.buildIndex);   
            GameObject[] gb2=scene2.GetRootGameObjects();
            Debug.Log(gb2.Length);
        }


    // Update is called once per frame
    void Update()
    {
        
    }
}

3.6 场景的叠加效果

  • 多个场景一起生效,叠加,效果
  • 从 Hierarchy 窗口里可以看到
  • 现在有3个场景,同时生效了,场景内的gb也都显示出来了

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        ///先查看当前Scene
        //获取当前场景
        Scene scene1=SceneManager.GetActiveScene();

        //场景名称
        Debug.Log(scene1.name);

         //场景路径
        Debug.Log(scene1.path);      
    
        //场景索引
        Debug.Log(scene1.buildIndex);   
        GameObject[] gb1=scene1.GetRootGameObjects();
        Debug.Log(gb1.Length);

        //跳转场景
        //SceneManager.LoadScene(2);
        //SceneManager.LoadScene("Scene2");

        //调用异步的Start1
        Start1();

        //统计已经加载的场景数量
        Debug.Log(SceneManager.sceneCount);

        //创建新场景:直接用代码
        Scene scene3=SceneManager.CreateScene("Scene3");

        //卸载场景
        //SceneManager.UnloadSceneAsync("Scene3");

        //同步加载场景,卡顿,等待
        SceneManager.LoadScene("Scene3");
        //SceneManager.loadScene("scene3",LoadSceneMode.Single);
        //SceneManager.loadScene("scene3",LoadSceneMode.Additive);

        //异步加载场景
        //SceneManager.loadSceneAsync("scene3");


    }

        async void Start1()
        {
            AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(2,LoadSceneMode.Additive);
            // 等待场景加载完成
            while (!asyncLoad.isDone)
            {
                await System.Threading.Tasks.Task.Yield();
            }
            // 场景加载完成后获取信息
            Debug.Log(SceneManager.GetActiveScene().name);

            //获取当前场景
            //新定义1个scene2  Scene scene2=
            Scene scene2=SceneManager.GetActiveScene();

            //场景是否已经加载, 但是可能还没有激活新的Scene
            Debug.Log(scene2.isLoaded); 

            ///再次查看当前Scene
            //场景名称
            Debug.Log(scene2.name);

            //场景路径
            Debug.Log(scene2.path);      
        
            //场景索引
            Debug.Log(scene2.buildIndex);   
            GameObject[] gb2=scene2.GetRootGameObjects();
            Debug.Log(gb2.Length);
        }


    // Update is called once per frame
    void Update()
    {
        
    }
}

4 同步和异步

4.1  同步和异步

  • 同步: 纯线性
  • 异步: 也是线性,但是只是逻辑上还是线性。但是有了分支,把消耗时间的操作,放到其他线程里去执行

下面几个图都是网上找的参考的

4.2 多线程  协程

  • 多线程
  • 协程

4.2.1 多线程

多线程是一种同时运行多个执行路径的技术,每个执行路径称为一个线程。

多个线程可以在多核CPU上真正并行运行,或者在单核CPU上通过时间片轮转模拟并发。多线程通过操作系统调度,能够充分利用计算资源,在处理I/O密集型和CPU密集型任务时具有优势。

特点:
每个线程都有独立的栈空间和执行路径。
线程之间可以共享内存数据,因此需要进行同步控制,以避免数据竞争和死锁问题。
线程调度由操作系统控制,可能涉及上下文切换,带来一定的开销。

4.2.2 协程

协程是一种比线程更轻量级的并发实现方式。

与多线程不同,协程不是由操作系统调度,而是由编程语言或运行时环境来管理。

协程可以在需要时暂停自身,并将控制权交还给调用方,稍后再恢复执行。

它们适用于处理需要频繁暂停和恢复的任务,如异步I/O操作。

特点:
协程不会并行运行,单个线程中可以运行多个协程。
协程之间共享执行线程,但不需要上下文切换,切换开销非常小。
协程适用于I/O密集型任务,如网络请求、文件读写等,能够实现高效的异步操作。

4.3 异步加载场景UnityEngine.SceneManagement;

4.3.1 除了默认的,还需要额外导入其他包

using UnityEngine;

using UnityEngine.SceneManagement;

4.3.2  测试异步跳转场景,可成功

 去掉各种注释的代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//导入场景管理类
using UnityEngine.SceneManagement;

public class AsyncTest : MonoBehaviour
{

    void Start()
    {
        StartCoroutine(loadScene());
        
    }

    IEnumerator loadScene()
    {
        // 异步的协程
        AsyncOperation operation1=SceneManager.LoadSceneAsync(2);
        yield return operation1;
    }


    // Update is called once per frame
    void Update()
    {
        
    }
}

4.3.3 详细代码和注释

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//导入场景管理类
using UnityEngine.SceneManagement;

public class AsyncTest : MonoBehaviour
{
    //异步,需要先声明SceneManager.LoadSceneAsync(2)的返回值
    //AsyncOperation operation1;

    // Start is called before the first frame update
    void Start()
    {
        //协程不能直接LoadScene(),必须新建一个协程方法StartCoroutine
        StartCoroutine(loadScene());
        
    }

    //以协程的方法来异步加载场景
    //必须单独写一个 loadScene()方法,而不能用Application.LoadScene()方法
    //这个异步的方法,有返回值,返回值是固定的IEnumerator
    IEnumerator loadScene()
    {
        // 异步的协程
        // SceneManager.LoadSceneAsync()有返回值,返回值类型AsyncOperation
        AsyncOperation operation1=SceneManager.LoadSceneAsync(2);
        yield return operation1;
    }




    // Update is called once per frame
    void Update()
    {
        
    }
}

4.3.4 注释内容

     //异步,需要先声明SceneManager.LoadSceneAsync(2)的返回值

    // 也是可以在函数内,使用 operation1 时当时声明,  但是函数内声明的,函数外就无法条用operation1,所以为了外面可以调用,还是在外面声明

    //AsyncOperation operation1;

    // Start is called before the first frame update

    void Start()

    {

        //协程不能直接LoadScene(),必须新建一个协程方法StartCoroutine

        StartCoroutine(loadScene());

       

    }

    //以协程的方法来异步加载场景

    //必须单独写一个 loadScene()方法,而不能用Application.LoadScene()方法

    //这个异步的方法,有返回值,返回值是固定的IEnumerator

    IEnumerator loadScene()

    {

        // 异步的协程

        // SceneManager.LoadSceneAsync()有返回值,返回值类型AsyncOperation

       // 也可以在函数外,最开始声明

        AsyncOperation operation1=SceneManager.LoadSceneAsync(2);

        yield return operation1;

    }

5 加载进度

5.1  对应的协程的进度  operation1.progress

  • operation1.progress
  • 适合放在 void Update() 方法里去实现,因为逐帧加载。

5.2  关于进度的数值

  • unity里,输出进度 0-0.9,其中0.9 在unity里就是100%
  • 实际游戏里
  • 有的0.9-100%飞速,有的是按比例0.9折算到100%
  • 场景小异步加载也就很快

5.3 对应代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//导入场景管理类
using UnityEngine.SceneManagement;

public class AsyncTest : MonoBehaviour
{
    //异步,需要先声明SceneManager.LoadSceneAsync(2)的返回值
    AsyncOperation operation1;

    // Start is called before the first frame update
    void Start()
    {
        //协程不能直接LoadScene(),必须新建一个协程方法StartCoroutine
        StartCoroutine(loadScene());
        
    }

    //以协程的方法来异步加载场景
    //必须单独写一个 loadScene()方法,而不能用Application.LoadScene()方法
    //这个异步的方法,有返回值,返回值是固定的IEnumerator
    IEnumerator loadScene()
    {
        // 异步的协程
        // SceneManager.LoadSceneAsync()有返回值,返回值类型AsyncOperation
        operation1=SceneManager.LoadSceneAsync(2);
        yield return operation1;
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log(operation1.progress);
    }
}

5.4 如何做个显示的UI进度条

。。。。是个问题,学到了再说

6 按条件跳转新地图

6.1 延迟跳转

  • 跳转地图也可以不是即可生效的
  • 可以加定时器, 按任意键跳转,下面的例子可以实现10秒后跳转
  • 除了延迟跳转新地图,也可以设置其他条件:比如 响应键盘,UI等等

6.2 测试代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//导入场景管理类
using UnityEngine.SceneManagement;

public class AsyncTest : MonoBehaviour
{
    //异步,需要先声明SceneManager.LoadSceneAsync(2)的返回值
    AsyncOperation operation1;
    float timer1=0;

    // Start is called before the first frame update
    void Start()
    {
        //协程不能直接LoadScene(),必须新建一个协程方法StartCoroutine
        StartCoroutine(loadScene());
        
    }

    //以协程的方法来异步加载场景
    //必须单独写一个 loadScene()方法,而不能用Application.LoadScene()方法
    //这个异步的方法,有返回值,返回值是固定的IEnumerator
    IEnumerator loadScene()
    {
        // 异步的协程
        // SceneManager.LoadSceneAsync()有返回值,返回值类型AsyncOperation
        operation1=SceneManager.LoadSceneAsync(2);
        operation1.allowSceneActivation=false;
        yield return operation1;
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log(operation1.progress);
        timer1=timer1+Time.deltaTime;
        if (timer1>10)
        {
        operation1.allowSceneActivation=true;
        }
    }
}


http://www.kler.cn/a/525826.html

相关文章:

  • 前端axios拦截器
  • 从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(基础图形库实现)
  • Win11下帝国时代2无法启动解决方法
  • (一)QT的简介与环境配置WIN11
  • 区块链的数学基础:核心原理与应用解析
  • CTF-web: Python YAML反序列化利用
  • 前端进阶:深度剖析预解析机制
  • 电梯系统的UML文档13
  • 跟李沐学AI:视频生成类论文精读(Movie Gen、HunyuanVideo)
  • python学opencv|读取图像(五十一)使用修改图像像素点上BGR值实现图像覆盖效果
  • java求职学习day19
  • AI协助探索AI新构型的自动化创新概念
  • 8641 冒泡排序
  • 【教学类-89-03】20250113新年篇03——福字贴(PPTX艺术字-空心字)
  • 我的求职面经:(2)C++中空指针请使用nullptr不要使用NULL
  • Haproxy介绍及学习
  • 代码随想录_栈与队列
  • 1/30每日一题
  • 课题推荐:基于matlab,适用于自适应粒子滤波的应用
  • [权限提升] Windows 提权 — 系统内核溢出漏洞提权
  • 三路排序算法
  • 拼车(1094)
  • 在汇编语言中,ASSUME 是一个用于告诉汇编器如何将段寄存器与特定段名称关联的指令
  • AutoDL 云服务器:xfce4 远程桌面 终端乱码 + 谷歌浏览器
  • oracl:数据查询语言DQL
  • 密码强度验证代码解析:C语言实现与细节剖析