unity3dloading界面异步加载进度条
根据宣雨松前辈的教程来做的,因为我用到的场景不是在游戏里的那种(本人做增强现实的,完全把unity拿来做应用了=。=),所以这里的方法不是很全面
异步加载流程:
lovdlevel 异步读取
A---------------> B ------------------------>C
播放加载动画
示例背景介绍:A场景是一个菜单,鼠标选中其中一项,则跳转到相应场景(C场景),B场景为加载动画播放场景
A场景:摄像机添加menu.cs
B场景:绑定loading.cs,把loading图片附到loading.cs
menu.cs:
[csharp]view plaincopy
1. usingUnityEngine;
2. usingSystem.Collections;
3.
4. publicclassGlobe{
5. //在这里记录当前切换场景的名称
6. publicstaticstringloadName;
7. }
8. publicclassmenu : MonoBehaviour {
9.
10. // Use this for initialization
11. voidStart ()
12. {
13.
14. }
15.
16. // Update is called once per frame
17. voidUpdate ()
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, outhit) )
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. usingUnityEngine;
2. usingSystem.Collections;
3.
4. publicclassloading : MonoBehaviour {
5.
6. privatefloatfps = 1000.0f;
7. privatefloattime;
8. //一组动画的贴图,在编辑器中赋值。
9. publicTexture2D[] animations;
10. privateintnowFram;
11. //异步对象
12. AsyncOperation async;
13.
14. //读取场景的进度,它的取值范围在0 - 1 之间。
15. intprogress = 1;
16.
17. voidStart()
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 returnasync;
33.
34. }
35.
36. voidOnGUI()
37. {
38. //因为在异步读取场景,
39. //所以这里我们可以刷新UI
40. DrawAnimation(animations);
41.
42. }
43.
44. voidUpdate()
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(newRect( (Screen.width-60)*0.5f,(Screen.height-60)*0.5f,60,60) ,tex[nowFram] );
77. //在这里显示读取的进度。
78. GUI.Label(newRect( (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 方法将枚举数提前到集合的第一个元素。
在调用 MoveNext 或 Reset 之前,Current 返回同一对象。MoveNext 将 Current
如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对 MoveNext 的后续调用也返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext。
只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,并且下一次对 MoveNext 或 Reset 的调用将引发 n。如果在 MoveNext 和 Current 之间修改集合,那么即使枚举数已经无效,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);
}
}