当前位置:   article > 正文

试用Unity3D体验(三):添加Loading页面_unity 3d 放入浏览器

unity 3d 放入浏览器

上一篇【试用Unity3D体验(二):添加一个启动界面

本次目标

上一篇做完启动页面有2个问题,

  1. 从启动页面跳转到游戏场景以后,本来应该隐藏的鼠标没有隐藏(同时也担心将来回到启动页面鼠标不出现)
  2. 点击新游戏以后,会有很长时间的卡顿。这个是加载场景导致的(如果只是例子不会,例子里的playground场景其实没有多少东西)。

本次主要是解决这两个问题。

鼠标的问题

这个比较简单,我们在跳转新场景的时候把鼠标锁定,然后回来以后在启动的时候接触锁定。这个需求是针对我们的场景来说的,我们的场景要求游戏的时候不显示鼠标。

上次我们创建了一个 ButtonClick 代码,这个现在看起来名字不是很合适,我们先调整名称为 IndexController,然后修改其代码如下:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.SceneManagement;
  5. public class IndexController : MonoBehaviour
  6. {
  7. // Start is called before the first frame update
  8. void Start()
  9. {
  10. Cursor.visible = true;
  11. Cursor.lockState = CursorLockMode.None;
  12. }
  13. // Update is called once per frame
  14. void Update()
  15. {
  16. }
  17. public void StartGame()
  18. {
  19. Cursor.visible = false;
  20. Cursor.lockState = CursorLockMode.Locked;
  21. SceneManager.LoadScene("Playground");
  22. }
  23. }

在点击启动按钮的时候把鼠标锁定隐藏,在加载的时候显示出来。当然,隐藏的动作放到下一个场景的Start来做更合适一些。但是我就是懒得修改了,先挖一个坑给后人。

添加Loading场景

大部分游戏都有一个Loading场景,比如这样的:

2a3a6827bd7cc79c6390966888e65098.png

我们也计划做一个这样的动画,在页面加载的时候给用户更好的体验效果。不过为了简单,我们不做进度条了,做一个转圈的效果就好了。

和上一篇一样,我们新建并保存一个场景,起名Loading。添加画布和图像,然后从网上找到授权为 Free 的图片作为背景。 别忘记了加摄像头和修改 EventSystem 的 Input Module; 这些调整完的效果如下:

我这里随意找了一张图片,重点是授权是免费的,这一定要非常确认。不要忽略任何素材的版权问题,不要忽略任何素材的版权问题、不要忽略任何素材的版权问题。宁可不用,也不要用未授权图片。推荐使用 bing 查询,筛选条件 选择 free 。

PS:不要吐槽我们的图片的不搭配,我们目前体验功能是首位。这些可以后期找有缘人去修改(如果有那么一天的话)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSp5Yqp5by66ICF,size_20,color_FFFFFF,t_70,g_se,x_16

这里有2个问题:

  1. 我们希望这个Loading页面尽可能被复用,也就是说它异步加载的场景是不固定的
  2. 需要做消息的传递,有可能上一个场景需要传递消息给下一个场景

检查了一下SceneManager.LoadScene ,然而它并没有能传递消息的功能,所以我们需要想别的方式处理。最简单的方式:static。我们创建一个 LoadingHelper 的类,它每次先加载 Loading 场景,然后由 Loading 场景去加载我们真实要加载的场景。 

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.SceneManagement;
  6. public class LoadingHelper
  7. {
  8. public static LoadingHelper Instance = new LoadingHelper();
  9. private const string LoadingSceneName = "Loading";
  10. private const string DefaultSceneName = "Index";
  11. private bool isLoading = false;
  12. private string nextSceneName = null;
  13. public void LoadScene(string sceneName, Dictionary<string, object> sceneOneshotData = null)
  14. {
  15. if (isLoading)
  16. {
  17. Debug.LogError("The last one was still being doing.");
  18. return;
  19. }
  20. this.isLoading = true;
  21. this.nextSceneName = string.IsNullOrWhiteSpace(sceneName) ? DefaultSceneName : sceneName;
  22. SceneOneshotDataManager.Instance.WriteSceneData(sceneOneshotData);
  23. SceneManager.LoadScene(LoadingSceneName, LoadSceneMode.Single);
  24. }
  25. public string GetNextSceneName()
  26. {
  27. return this.nextSceneName;
  28. }
  29. public void FinishLoading()
  30. {
  31. this.nextSceneName = null;
  32. this.isLoading = false;
  33. }
  34. }

我们还定义了一个 SceneOneshotDataManager 类,它负责传递数据。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class SceneOneshotDataManager
  5. {
  6. public static SceneOneshotDataManager Instance = new SceneOneshotDataManager();
  7. Dictionary<string, object> sceneOneshotData = null;
  8. public bool Exist()
  9. {
  10. return sceneOneshotData != null;
  11. }
  12. public bool WriteSceneData(Dictionary<string, object> data)
  13. {
  14. if (this.sceneOneshotData != null)
  15. {
  16. Debug.LogError("The last data was not used.");
  17. return false;
  18. }
  19. this.sceneOneshotData = data;
  20. return true;
  21. }
  22. public Dictionary<string, object> ReadSceneData()
  23. {
  24. Dictionary<string, object> result = sceneOneshotData;
  25. sceneOneshotData = null;
  26. return result;
  27. }
  28. }

然后我们打开之前的 IndexController 类,修改 StartGame 的代码:

  1. public void StartGame()
  2. {
  3. Cursor.visible = false;
  4. Cursor.lockState = CursorLockMode.Locked;
  5. LoadingHelper.Instance.LoadScene("Playground");
  6. }

和之前一样,在【生成设置】里添加我们新的 Loading 场景。然后测试一下,现在跳转到 Loading 的页面了。

接下来我们创建一个 LoadingContrller 脚本,并添加到画布

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSp5Yqp5by66ICF,size_18,color_FFFFFF,t_70,g_se,x_16

然后修改脚本,在 Start 的时候获取真正要跳转的场景名称,并且动态加载。首先先禁用了鼠标,用户安心的看 Loading 就好了。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.SceneManagement;
  5. public class LoadingController : MonoBehaviour
  6. {
  7. // Start is called before the first frame update
  8. void Start()
  9. {
  10. Cursor.visible = false;
  11. Cursor.lockState = CursorLockMode.Locked;
  12. var nextSceneName = LoadingHelper.Instance.GetNextSceneName();
  13. StartCoroutine(loadScene(nextSceneName));
  14. }
  15. private IEnumerator loadScene(string sceneName)
  16. {
  17. AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
  18. while (!asyncLoad.isDone)
  19. {
  20. yield return null;
  21. }
  22. }
  23. }

执行以下,完美。接下来我们对 Loading 做一些美化。这里不用进度条,我们就做一个问题提升吧。在屏幕下面添加一航文字 【按任意键继续】。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSp5Yqp5by66ICF,size_20,color_FFFFFF,t_70,g_se,x_16

然后修改一下 LoadingController 脚本,找了一堆古典词句。这里因为示例里playground场景内容太少,本来就是一下加载完成了,所以只能通过 yield return new WaitForSeconds(15); 这里模拟时间,后期可以去掉

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.InputSystem;
  5. using UnityEngine.SceneManagement;
  6. using UnityEngine.UI;
  7. public class LoadingController : MonoBehaviour
  8. {
  9. private bool finish = false;
  10. private AsyncOperation asyncLoad;
  11. private string PressAnyKeyString = "按任意键继续!";
  12. private string[] messages = new string[11] {
  13. "时间,转瞬即逝,不复再来。",
  14. "夫天地者,万物之逆旅也。",
  15. "时间,转瞬即逝,不复再来。",
  16. "少年易老学难成,一寸光阴不可轻。",
  17. "草木也知愁,韶华竟白头。",
  18. "少年辛苦终身事,莫向光阴惰寸功。",
  19. "读书不觉已春深,一寸光阴一寸金。",
  20. "仰天大笑出门去,我辈岂是蓬蒿人。",
  21. "长风破浪会有时,直挂云帆济沧海。",
  22. "书山有路勤为径,学海无涯苦作舟。",
  23. "千磨万击还坚劲,任尔东西南北风。"
  24. };
  25. public Text PressAnyKey;
  26. // Start is called before the first frame update
  27. void Start()
  28. {
  29. if (this.PressAnyKey == null)
  30. {
  31. Debug.LogError("Please select the text box.");
  32. return;
  33. }
  34. Cursor.visible = false;
  35. Cursor.lockState = CursorLockMode.Locked;
  36. this.finish = false;
  37. this.PressAnyKey.text = string.Empty;
  38. StartCoroutine(slideshow());
  39. var nextSceneName = LoadingHelper.Instance.GetNextSceneName();
  40. StartCoroutine(loadScene(nextSceneName));
  41. }
  42. void Update()
  43. {
  44. pressAnyKey();
  45. }
  46. private IEnumerator loadScene(string sceneName)
  47. {
  48. if (string.IsNullOrWhiteSpace(sceneName))
  49. {
  50. Debug.LogError("Please input the next scene name.");
  51. yield return null;
  52. }
  53. else
  54. {
  55. this.asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
  56. this.asyncLoad.allowSceneActivation = false;
  57. while (this.asyncLoad.progress < 0.9f)
  58. {
  59. yield return new WaitForSeconds(15); //fake
  60. //yield return WaitForEndOfFrame;
  61. }
  62. this.finish = true;
  63. this.PressAnyKey.text = PressAnyKeyString;
  64. yield return new WaitForEndOfFrame();
  65. }
  66. }
  67. private IEnumerator slideshow()
  68. {
  69. while (!this.finish)
  70. {
  71. int n = (int)(Random.value * 10);
  72. var message = messages[n];
  73. this.PressAnyKey.text = message;
  74. yield return new WaitForSeconds(5);
  75. }
  76. }
  77. private void pressAnyKey()
  78. {
  79. if (this.finish
  80. && (
  81. (Gamepad.current != null && Gamepad.current.aButton.isPressed)
  82. || (Keyboard.current != null && Keyboard.current.anyKey.isPressed)
  83. )
  84. )
  85. {
  86. this.asyncLoad.allowSceneActivation = true;
  87. }
  88. }
  89. }

运行一下,看起来还不错。今天太晚了,参数跨场景传递的内容明天再测试吧。

最后提示一下,脚本里定义了一个 Text PressAnyKey 属性,这个没有在代码里初始化。初始化的方式我采用的是在检查器里进行配置。

 再见。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/125210
推荐阅读
相关标签
  

闽ICP备14008679号