文档章节

unity 3d 异步加载场景--异步预加载场景

asdtiang
 asdtiang
发布于 2017/05/02 18:24
字数 735
阅读 885
收藏 0

unity版本5.3以上

网上很多异步加载场景实际上没有做到异步的功能,大部分是显示一个进度条,然后同时在执行异步加载代码,这实际上并未异步加载,这只是后台加载,并且性能上比同步加载慢,原因如下:

SceneManager.LoadSceneAsync 这个方法会在后台启动一个线程去加载场景,如果同时显示加载的进度条,这个进度条为主线程,这里就有两个线程在去抢占资源,因此从时间来讲,肯定比直接加载场景要慢。

那么问题来了,如何做到无延迟加载呢,前提条件:假设设备的资源是足够去同时加载两个场景。只需要在运行的场景内,提前把下一个要用的场景加载好,切换场景时无需再加载场景资源,这样处理后切换基本上是无延迟切换。

示例代码如下:

using System;
using UnityEngine;
using UnityEngine.SceneManagement;

/// <summary>
/// 此类提供异步缓存加载场景(目前仅支持缓存加载一个场景),注意:在unity编辑器里调试时,异步加载会阻塞主线程,打包后,异步加载不会阻塞主线程,
/// 具体参考: https://forum.unity3d.com/threads/scenemanager-loadsceneasync-not-working-as-expected.369714/ 
/// </summary>
public class CacheSceneManager : MonoBehaviour {

    public static CacheSceneManager _instance;
    
    /// <summary>
    /// 预加载场景名称
    /// </summary>
    public string CacheSceneName;
    private  AsyncOperation async;
    private bool cacheFinish = false;
    private bool cacheStart = true;
    private bool startLoadScene = false;
    private long startLoadTime = 0;
    private long cacheAfterSeconds = 2;

    void Awake()
    {
        //设置后台加载线程的优
        Application.backgroundLoadingPriority = ThreadPriority.BelowNormal;
        cacheFinish = false;
        _instance = this;
        if (CacheSceneName!=null) {
            CacheSceneManager._instance.cacheScene(CacheSceneName);
        }
    }   

    private void cacheScene(string name) {
        CacheSceneName = name;
        cacheFinish = false;
        cacheStart = false;
        startLoadScene = false;
        startLoadTime = 0;
        async = null;
    }

    void Update()
    {
        //在脚本加载完成后延迟2秒钟开始缓存,避免和主场景抢占资源,具体时间可根据主场景的大小以及实际情况来设置
        if (!cacheStart) {
            if (startLoadTime==0) {
                startLoadTime = getCurrentTimeSeconds();
            }
            if ((getCurrentTimeSeconds() - startLoadTime) > cacheAfterSeconds) {
                cacheStart = true;
                Debug.Log(CacheSceneName + " start async cache---------------------->" + getCurrentTimeSeconds());
                async = SceneManager.LoadSceneAsync(CacheSceneName);
                async.allowSceneActivation = false;
            }
        }
        
        if (async!=null) {
            //如果加载完成则更新标记
            if (async.progress == 0.9f && !cacheFinish)
            {
                cacheFinish = true;
                Debug.Log(CacheSceneName + " end async cache--------------------------> use Time:" + (getCurrentTimeSeconds() - startLoadTime- cacheAfterSeconds));
            }
            //加载完成后,检测到切换场景时,加载缓存场景
            if (async.progress == 0.9f && startLoadScene)
            {
                async.allowSceneActivation = true;
            }

        }
    }
    //需要加载缓存场景时调用 CacheSceneManager._instance.startLoad(); 
    public void startLoad() {
        startLoadScene = true;
    }

    public static long getCurrentTimeSeconds()
    {
        return ConvertDateTimeToInt(System.DateTime.Now) / 1000;

    }

    public static long ConvertDateTimeToInt(System.DateTime time)
    {
        System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
        long t = (time.Ticks - startTime.Ticks) / 10000;
        return t;
    }

}

注意:在unity编辑器里调试时,异步加载会阻塞主线程,打包后,异步加载不会阻塞主线程,
具体参考: https://forum.unity3d.com/threads/scenemanager-loadsceneasync-not-working-as-expected.369714/
 

本文转载自:http://www.asdtiang.org/2017/05/02/unity-3d-%e5%bc%82%e6%ad%a5%e5%8a%a0%e8%bd%bd%e5%9c%ba%e6%99%af-%

共有 人打赏支持
asdtiang
粉丝 16
博文 60
码字总数 4329
作品 0
成都
架构师
私信 提问
Unity实战问题--Loading更好的实现方式(场景进度条问题) 转+原

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27489007/article/details/83654442 注:前面半部分属于转载的文章,因为参考的文章也是转载的,没找到原创...

秋隆
2018/11/02
0
0
【文集】Unity中的异步编程技术

什么是异步编程?异步编程是指由于异步 I/O 等因素,无法同步获得执行结果时,在回调函数 中进行下一步操作,这个技术在游戏这种强调快速响应的应用中很重要,让我们一起看一个通用的介绍: Un...

CatherinePlans
2017/11/05
0
0
Blend4Web vs Unity: WebGL 的性能比较

编者序言 这篇文章最初在 Habrahabr发表 ,它是一个流行于 IT 专业人员的俄罗斯网站。这个主题主题引发了成千上万读者的兴趣并留下了几十个评论。我们很乐意的介绍这个关于 Unity WebGL 和 ...

yuri_s8s
2016/12/29
0
0
Blend4Web vs Unity: WebGL 的性能比较

编者序言 这篇文章最初在 Habrahabr发表 ,它是一个流行于 IT 专业人员的俄罗斯网站。这个主题主题引发了成千上万读者的兴趣并留下了几十个评论。我们很乐意的介绍这个关于 Unity WebGL 和 ...

yuri_s8s
2016/12/29
0
0
Ellan/StarForce

官方网站 简体中文 - http://gameframework.cn/ QQ 讨论群 216332935 Star Force 简介 Star Force 是一个使用 Game Framework 游戏框架制作的游戏演示项目,主要目的是对 Game Framework 的使...

Ellan
2018/05/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

想问一下C++里queue要怎么遍历

如题,想知道怎么遍历<queue>对象的元素? 貌似不能遍历。要么全部pop push一遍,要么换个容器呗。 queue是先进后出的数据类型,只能不断读top()然后再pop()掉。故意把遍历操作隐藏掉了,...

shzwork
昨天
2
0
Ubuntu 18.04.2 LTS nvidia-docker2 : 依赖: docker-ce (= 5:18.09.0~3-0~ubuntu-bionic)

平台:Ubuntu 18.04.2 LTS nvidia-docker2 版本:2.0.3 错误描述:在安装nvidia-docker2的时候报dpkg依赖错误 nvidia-docker2 : 依赖: docker-ce (= 5:18.09.0~3-0~ubuntu-bionic) 先看一下依......

Pulsar-V
昨天
2
0
学习笔记1-goland结构体(struct)

写在前面:若有侵权,请发邮件by.su@qq.com告知。 转载者告知:如果本文被转载,但凡涉及到侵权相关事宜,转载者需负责。请知悉! 本文永久更新地址:https://my.oschina.net/bysu/blog/3036...

不最醉不龟归
昨天
3
0
【转】go get命令使用socket代理

由于某些不可描述的原因,国内使用go get命令安装某些包的时候会超时导致失败,比如net包、sys包、tools包等。第一种解决办法就是自己从git上下载后添加链接到GOPATH中,比如: 1234...

yiduwangkai
昨天
6
0
从上往下打印出二叉树的每个节点,同层节点从左至右打印。

//第一种做法 public class Solution { public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList <Integer> li=new ArrayList<Integer>(); ArrayList <TreeN......

南桥北木
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部