unity3d异步加载场景

发布于:2021-12-01 00:43:01

?






unity3dloading界面异步加载进度条


根据宣雨松前辈的教程来做的,因为我用到的场景不是在游戏里的那种(本人做增强现实的,完全把unity拿来做应用了=。=),所以这里的方法不是很全面,原文戳这里:点击打开链接


?


异步加载流程:


?


? ? lovdlevel ? ? ? ? ? ? ? ? ?异步读取
A---------------> B ------------------------>C
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?播放加载动画


?


示例背景介绍:A场景是一个菜单,鼠标选中其中一项,则跳转到相应场景(C场景),B场景为加载动画播放场景


A场景:摄像机添加menu.cs
B场景:绑定loading.cs,把loading图片附到loading.cs

menu.cs:


[csharp]?view plaincopy



1.? using?UnityEngine;??


2.? using?System.Collections;??


3.? ??


4.? public?class?Globe{??


5.? ?????????//在这里记录当前切换场景的名称??


6.? ?????public?static?string?loadName;??


7.? }??


8.? public?class?menu?:?MonoBehaviour?{??


9.? ??


10.????//?Use?this?for?initialization??


11.????void?Start?()???


12.????{??


13.??????????


14.????}??


15.??????


16.????//?Update?is?called?once?per?frame??


17.????void?Update?()???


18.????{??


19.????????if?(Input.GetKey(KeyCode.Escape))??


20.????????????Application.Quit();??


21.????????Camera?cam?=?Camera.mainCamera;??


22.????????if?(Input.GetMouseButtonDown(0))??


23.????????{???


24.????????????Ray?ray?=?cam.ScreenPointToRay(Input.mousePosition);??


25.????????????RaycastHit?hit;??


26.????????????if?(Physics.Raycast(ray,?out?hit)?)??


27.????????????{??


28.????????????????switch?(hit.collider.name)??


29.????????????????{??


30.??????????????????????


31.????????????????????case?"***":??


32.????????????????????????Globe.loadName?=?"C";??


33.????????????Application.LoadLevel?("B");??????


34.????????????????????????break;??


35.????????????????????case?"***":??


36.????????????Globe.loadName?=?"CCC";??


37.????????????Application.LoadLevel?("B");??


38.????????????break;????


39.??????????????????


40.????????????????}??????????????????


41.????????????}??


42.????????}?????????


43.????}??


44.}??




loading.cs


[csharp]?view plaincopy



1.? using?UnityEngine;??


2.? using?System.Collections;??


3.? ??


4.? public?class?loading?:?MonoBehaviour?{??


5.? ??


6.? ????private?float?fps?=?1000.0f;??


7.? ????private?float?time;??


8.? ????//一组动画的贴图,在编辑器中赋值。??


9.? ????public?Texture2D[]?animations;??


10.????private?int?nowFram;??


11.????//异步对象??


12.????AsyncOperation?async;??


13.??


14.????//读取场景的进度,它的取值范围在0?-?1?之间。??


15.????int?progress?=?1;??


16.??


17.????void?Start()??


18.????{??


19.????????//在这里开启一个异步任务,??


20.????????//进入loadScene方法。??


21.????????StartCoroutine(loadScene());??


22.????}??


23.??


24.????//注意这里返回值一定是?IEnumerator??


25.????IEnumerator?loadScene()??


26.????{??


27.????????//异步读取场景。??


28.????????//Globe.loadName?就是A场景中需要读取的C场景名称。??


29.????????async?=?Application.LoadLevelAsync(Globe.loadName);??


30.??


31.????????//读取完毕后返回,?系统会自动进入C场景??


32.????????yield?return?async;??


33.??


34.????}??


35.??


36.????void?OnGUI()??


37.????{??


38.????????//因为在异步读取场景,??


39.????????//所以这里我们可以刷新UI??


40.????????DrawAnimation(animations);??


41.??


42.????}??


43.??


44.????void?Update()??


45.????{??


46.??


47.????????//在这里计算读取的进度,??


48.????????//progress?的取值范围在0.1?-?1之间,?但是它不会等于1??


49.????????//也就是说progress可能是0.9的时候就直接进入新场景了??


50.????????//所以在写进度条的时候需要注意一下。??


51.????????//为了计算百分比?所以直接乘以100即可??


52.????????progress?=??(int)(async.progress?*100);??


53.??


54.????????//有了读取进度的数值,大家可以自行制作进度条啦。??


55.????????Debug.Log(progress);??


56.??


57.????}??


58.????//简单绘制2D动画??


59.????void??DrawAnimation(Texture2D[]?tex)??


60.????{??


61.??


62.????????time?+=?Time.deltaTime;??


63.??


64.?????????if(time?>=?1.0?/?fps){??


65.??


66.?????????????nowFram++;??


67.??


68.?????????????time?=?0;??


69.??


70.?????????????if(nowFram?>=?tex.Length)??


71.?????????????{??


72.????????????????nowFram?=?0;??


73.?????????????}??


74.????????}??


75.??????????


76.????????GUI.DrawTexture(new?Rect(?(Screen.width-60)*0.5f,(Screen.height-60)*0.5f,60,60)?,tex[nowFram]?);??


77.????????????????//在这里显示读取的进度。??


78.????????GUI.Label(new?Rect(?(Screen.width-100)*0.5f,(Screen.height-60)*0.5f+100,100,60),?"LOADING..."?+?progress+"%");??


79.??


80.????}??



?


?


?


?


IEnumerator 接口
语法



C#


C++


VB





IEnumerator 是所有非泛型枚举数的基接口。


有关此接口的泛形版本,请参见 IEnumerator。


C# 语言的 foreach 语句(在 Visual Basic 中为 for each)隐藏了枚举数的复杂性。因此,建议使用 foreach,而不直接操作枚举数。


枚举数可用于读取集合中的数据,但不能用于修改基础集合。


最初,枚举数定位在集合中第一个元素前。Reset 方法还会将枚举数返回到此位置。在此位置,调用 Current 属性会引发异常。因此,在读取 Current 的值之前,必须调用 MoveNext 方法将枚举数提前到集合的第一个元素。


在调用 MoveNextReset 之前,Current 返回同一对象。MoveNextCurrent 设置为下一个元素。


如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对 MoveNext 的后续调用也返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext


只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,并且下一次对 MoveNextReset 的调用将引发 InvalidOperationException。如果在 MoveNextCurrent 之间修改集合,那么即使枚举数已经无效,Current 也将返回它所设置成的元素。


枚举数没有对集合的独占访问权;因此,枚举通过集合在本质上不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。


示例



下面的代码示例演示如何实现自定义集合的 IEnumerable 和 IEnumerator 接口。在此示例中,没有显式调用这些接口的成员,但实现了它们,以便支持使用 foreach(在 Visual Basic 中为 for each)循环访问该集合。


C#


VB


复制


using System;

using System.Collections;

?

public class Person

{

??? public Person(string fName, string lName)

??? {

??????? this.firstName = fName;

??????? this.lastName = lName;

??? }

?

??? public string firstName;

??? public string lastName;

}

?

public class People : IEnumerable

{

??? private Person[] _people;

??? public People(Person[] pArray)

??? {

??????? _people = new Person[pArray.Length];

?

??????? for (int i = 0; i < pArray.Length; i++)

??????? {

??????????? _people[i] = pArray[i];

??????? }

??? }

?

??? public IEnumerator GetEnumerator()

??? {

??????? return new PeopleEnum(_people);

??? }

}

?

public class PeopleEnum : IEnumerator

{

??? public Person[] _people;

?

??? // Enumerators are positioned before the first element

??? // until the first MoveNext() call.

??? int position = -1;

?

??? public PeopleEnum(Person[] list)

??? {

??????? _people = list;

??? }

?

??? public bool MoveNext()

??? {

??????? position++;

??????? return (position < _people.Length);

??? }

?

??? public void Reset()

??? {

??????? position = -1;

??? }

?

??? public object Current

??? {

??????? get

??????? {

??????????? try

??????????? {

??????????????? return _people[position];

??????????? }

??????????? catch (IndexOutOfRangeException)

??????????? {

??????????????? throw new InvalidOperationException();

??????????? }

??????? }

??? }

}

?

class App

{

??? static void Main()

??? {

??????? Person[] peopleArray = new Person[3]

??????? {

??????????? new Person("John", "Smith"),

??????????? new Person("Jim", "Johnson"),

??????????? new Person("Sue", "Rabon"),

??????? };

?

??????? People peopleList = new People(peopleArray);

??????? foreach (Person p in peopleList)

??????????? Console.WriteLine(p.firstName + " " + p.lastName);

?

??? }

}

?

相关推荐

最新更新

猜你喜欢