试用Unity3D体验(三):添加Loading页面
上一篇【试用Unity3D体验(二):添加一个启动界面】
本次目标
上一篇做完启动页面有2个问题,
- 从启动页面跳转到游戏场景以后,本来应该隐藏的鼠标没有隐藏(同时也担心将来回到启动页面鼠标不出现)
- 点击新游戏以后,会有很长时间的卡顿。这个是加载场景导致的(如果只是例子不会,例子里的playground场景其实没有多少东西)。
本次主要是解决这两个问题。
鼠标的问题
这个比较简单,我们在跳转新场景的时候把鼠标锁定,然后回来以后在启动的时候接触锁定。这个需求是针对我们的场景来说的,我们的场景要求游戏的时候不显示鼠标。
上次我们创建了一个 ButtonClick 代码,这个现在看起来名字不是很合适,我们先调整名称为 IndexController,然后修改其代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class IndexController : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Cursor.visible = true;Cursor.lockState = CursorLockMode.None;}// Update is called once per framevoid Update(){}public void StartGame(){Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;SceneManager.LoadScene("Playground");}
}
在点击启动按钮的时候把鼠标锁定隐藏,在加载的时候显示出来。当然,隐藏的动作放到下一个场景的Start来做更合适一些。但是我就是懒得修改了,先挖一个坑给后人。
添加Loading场景
大部分游戏都有一个Loading场景,比如这样的:
我们也计划做一个这样的动画,在页面加载的时候给用户更好的体验效果。不过为了简单,我们不做进度条了,做一个转圈的效果就好了。
和上一篇一样,我们新建并保存一个场景,起名Loading。添加画布和图像,然后从网上找到授权为 Free 的图片作为背景。 别忘记了加摄像头和修改 EventSystem 的 Input Module; 这些调整完的效果如下:
我这里随意找了一张图片,重点是授权是免费的,这一定要非常确认。不要忽略任何素材的版权问题,不要忽略任何素材的版权问题、不要忽略任何素材的版权问题。宁可不用,也不要用未授权图片。推荐使用 bing 查询,筛选条件 选择 free 。
PS:不要吐槽我们的图片的不搭配,我们目前体验功能是首位。这些可以后期找有缘人去修改(如果有那么一天的话)
这里有2个问题:
- 我们希望这个Loading页面尽可能被复用,也就是说它异步加载的场景是不固定的
- 需要做消息的传递,有可能上一个场景需要传递消息给下一个场景
检查了一下SceneManager.LoadScene ,然而它并没有能传递消息的功能,所以我们需要想别的方式处理。最简单的方式:static。我们创建一个 LoadingHelper 的类,它每次先加载 Loading 场景,然后由 Loading 场景去加载我们真实要加载的场景。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class LoadingHelper
{public static LoadingHelper Instance = new LoadingHelper();private const string LoadingSceneName = "Loading";private const string DefaultSceneName = "Index";private bool isLoading = false;private string nextSceneName = null;public void LoadScene(string sceneName, Dictionary<string, object> sceneOneshotData = null){if (isLoading){Debug.LogError("The last one was still being doing.");return;}this.isLoading = true;this.nextSceneName = string.IsNullOrWhiteSpace(sceneName) ? DefaultSceneName : sceneName;SceneOneshotDataManager.Instance.WriteSceneData(sceneOneshotData);SceneManager.LoadScene(LoadingSceneName, LoadSceneMode.Single);}public string GetNextSceneName(){return this.nextSceneName;}public void FinishLoading(){this.nextSceneName = null;this.isLoading = false;}
}
我们还定义了一个 SceneOneshotDataManager 类,它负责传递数据。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SceneOneshotDataManager
{public static SceneOneshotDataManager Instance = new SceneOneshotDataManager();Dictionary<string, object> sceneOneshotData = null;public bool Exist(){return sceneOneshotData != null;}public bool WriteSceneData(Dictionary<string, object> data){if (this.sceneOneshotData != null){Debug.LogError("The last data was not used.");return false;}this.sceneOneshotData = data;return true;}public Dictionary<string, object> ReadSceneData(){Dictionary<string, object> result = sceneOneshotData;sceneOneshotData = null;return result;}
}
然后我们打开之前的 IndexController 类,修改 StartGame 的代码:
public void StartGame(){Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;LoadingHelper.Instance.LoadScene("Playground");}
和之前一样,在【生成设置】里添加我们新的 Loading 场景。然后测试一下,现在跳转到 Loading 的页面了。
接下来我们创建一个 LoadingContrller 脚本,并添加到画布
然后修改脚本,在 Start 的时候获取真正要跳转的场景名称,并且动态加载。首先先禁用了鼠标,用户安心的看 Loading 就好了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class LoadingController : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;var nextSceneName = LoadingHelper.Instance.GetNextSceneName();StartCoroutine(loadScene(nextSceneName));}private IEnumerator loadScene(string sceneName){AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);while (!asyncLoad.isDone){yield return null;}}
}
执行以下,完美。接下来我们对 Loading 做一些美化。这里不用进度条,我们就做一个问题提升吧。在屏幕下面添加一航文字 【按任意键继续】。
然后修改一下 LoadingController 脚本,找了一堆古典词句。这里因为示例里playground场景内容太少,本来就是一下加载完成了,所以只能通过 yield return new WaitForSeconds(15); 这里模拟时间,后期可以去掉
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;public class LoadingController : MonoBehaviour
{private bool finish = false;private AsyncOperation asyncLoad;private string PressAnyKeyString = "按任意键继续!";private string[] messages = new string[11] {"时间,转瞬即逝,不复再来。","夫天地者,万物之逆旅也。","时间,转瞬即逝,不复再来。","少年易老学难成,一寸光阴不可轻。","草木也知愁,韶华竟白头。","少年辛苦终身事,莫向光阴惰寸功。","读书不觉已春深,一寸光阴一寸金。","仰天大笑出门去,我辈岂是蓬蒿人。","长风破浪会有时,直挂云帆济沧海。","书山有路勤为径,学海无涯苦作舟。","千磨万击还坚劲,任尔东西南北风。"};public Text PressAnyKey;// Start is called before the first frame updatevoid Start(){if (this.PressAnyKey == null){Debug.LogError("Please select the text box.");return;}Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;this.finish = false;this.PressAnyKey.text = string.Empty;StartCoroutine(slideshow());var nextSceneName = LoadingHelper.Instance.GetNextSceneName();StartCoroutine(loadScene(nextSceneName));}void Update(){pressAnyKey();}private IEnumerator loadScene(string sceneName){if (string.IsNullOrWhiteSpace(sceneName)){Debug.LogError("Please input the next scene name.");yield return null;}else{this.asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);this.asyncLoad.allowSceneActivation = false;while (this.asyncLoad.progress < 0.9f){yield return new WaitForSeconds(15); //fake//yield return WaitForEndOfFrame;}this.finish = true;this.PressAnyKey.text = PressAnyKeyString;yield return new WaitForEndOfFrame();}}private IEnumerator slideshow(){while (!this.finish){int n = (int)(Random.value * 10);var message = messages[n];this.PressAnyKey.text = message;yield return new WaitForSeconds(5);}}private void pressAnyKey(){if (this.finish&& ((Gamepad.current != null && Gamepad.current.aButton.isPressed)|| (Keyboard.current != null && Keyboard.current.anyKey.isPressed))){this.asyncLoad.allowSceneActivation = true;}}
}
运行一下,看起来还不错。今天太晚了,参数跨场景传递的内容明天再测试吧。
最后提示一下,脚本里定义了一个 Text PressAnyKey 属性,这个没有在代码里初始化。初始化的方式我采用的是在检查器里进行配置。
再见。
试用Unity3D体验(三):添加Loading页面相关推荐
- vue如何整个页面添加loading
整个页面添加loading const loading = this.$loading({lock: true,fullscreen: true,text: '启动中',background:'rgb ...
- Angualr 加载速度慢,为页面初始化完成前添加loading
1.在项目根目录下index.html添加loading模板: <div class="loading-box" id="loading">< ...
- 06.简书项目实战三:详情页面和登录功能实现
简书项目实战三:详情页面和登录功能实现 1. 详情页面布局 这部分的布局比之前的简单多了,就一个标题加上主要内容而已. export default class Detail extends Comp ...
- Android:如何添加一个页面,如何跳转页面
一.如何为安卓添加多个页面 新建一个工程 打开这样 然后删掉 @Override public boolean onCreateOptionsMenu(Menu menu) { ...
- ant design表格添加loading效果
这里看一下ant design中表格添加loading效果. 在页面进来,获取数据时候 获取到数据的时候 实现方法: 这里只需要在要渲染的表格中添加,loading={XXXX} 即可.大括号里面的值 ...
- ecshop后台首页mysql_ecshop 添加后台页面以及设置权限
ecshop 添加新页面 给ecshop后台增加管理功能页面 比如我们增加一个统计报表叫做 物流费用统计报表 放在后台"报表统计"栏目中 具体操作步骤: 第一步,我们要添加一个菜单 ...
- Hexo(sakura)添加说说页面
前言 在自己的网站中添加说说页面,类似于qq空间一样: 实现操作也比较简单:css处理样式就好了, 这是静态处理的页面,如果有后台还可以实时添加发布说说,更高配一点. 快速传送门 步骤 在themes ...
- Unity3D项目三:牧师与魔鬼
Unity3D项目三:牧师与魔鬼 基本介绍 列出游戏中提及的事物(Objects) 牧师,恶魔,船,河流,左侧陆地,右侧陆地 用表格列出玩家动作表(规则表),注意,动作越少越好 动作 条件 结果 点击 ...
- 新闻添加html页面
新闻添加html页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="New ...
最新文章
- Shell tips
- Visual Assist x 无法自动补全Snippet提示的解决方法
- 【Android 逆向】Android 中常用的 so 动态库 ( 拷贝 /system/lib/ 中的 Android 系统 so 动态库 )
- c++经典书籍--深度探索C++对象模型
- 寒假每日一题(入门组)【week1 完结】
- VTK:小部件之TexturedButtonWidget
- VirtualBox虚拟机Ubuntu设置共享文件夹
- XCode的使用心得
- Apache-SimpleEmail 简单应用
- 前端学习(2718):重读vue电商网站38之通过input输入框优化
- 《剑指Offer》 合并两个排序的链表
- 完成课件中的动手动脑的或需要验证的相关内容。
- dns提供商主机名_在 Kubernetes 中使用 DNS 和 Headless Service 发现运行中的 Pod
- 企业中MySQL高可用集群架构三部曲之MM+keepalived
- Docker从理论到实践(九)------使用Dockerfile创建镜像
- JSON 的几种简单格式和转换
- 拨号保护,网络电话,保护隐私,匿名通话
- 【JAVA】金额工具类 金额千分位、中文大写金额、英文金额
- 等待页面所有图片加载完毕
- 中间件小师妹 de 年度工作总结
热门文章
- informatica 学习日记整理
- 三生三世十里桃花用计算机怎么弄,三生三世十里桃花灵宠系统怎么玩?三生三世十里桃花灵宠系统详解...
- 基石为勤能补拙的迷宫之旅——第十六天(包)
- 联想拯救者系列嗡嗡声,风扇狂转解决办法,亲测有效
- SAP中显示技术名称和描述的设置
- 【数据追梦人】毕业6年自学代码,2周面试30家企业,1年376张报表,选择决定人生!
- Cadence PCB层的概念
- 【物联网专题】1.1_物联网基本概念_什么是物联网(IoT)?
- UCI银行营销数据集--缺失值处理方法
- Matlab中统计矩阵中每个元素出现个数的方法-------tabulate()函数