1.在仅初始化一次的场景配置全局数据
游戏必定会存在场景转换的需求,但是有些数据我们是不想在每次加载新场景都实例化它的。
比如玩家的数据,网络管理器,声音管理器,全局管理器等等。
在Unity中有个接口,可以帮助我们实现这样的要求:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoundManager : MonoBehaviour {
private void Awake()
{
DontDestroyOnLoad(this);
}
}
方法DontDestoryOnLoad可以在加载新场景时保证对象不会被销毁,我们应当找一个空物体(一般叫GameManager),把全局的管理器脚本挂载到该Object上,在Awake中设定该语句。
假设我们把GameManager挂载到A场景下,转到B场景那么一切正常,我们可以看到GameManager上边有个DontDestoryOnLoad场景的标志。
不过你会发现一个问题,当你通过某种手段从B切换到A场景的时候,你会发现GameManager实例了两个:
所以,对于这种不想在加载新场景销毁的全局对象,我们的原则是把这些东西放在仅可能被一次实例化的场景里。
一般就是Login场景或者Launch场景。
2.异步加载场景进度条的设置
因为新的场景的资源可能还没有完全加载完毕,大多数游戏都会有一个转场。
在Unity中我们一般把转场单独设定为一个场景,这个场景除了一个进度条和一个背景图我们不加载任何资源,所以它的加载速度会非常的快。
在TransitionScene中创建一个空物体,将切换场景的控制脚本挂载到这上面。
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using Games.GlobeDefine;
using UnityEngine;
using UnityEngine.SceneManagement;
public class TransitionScene : MonoBehaviour
{
public Slider m_LoadingSlider;
public Text m_LoadingText;
private AsyncOperation m_AsyOperation;
private float m_LoadingProgress;
private float m_LoadingSpeed;
private void Start()
{
m_LoadingProgress = 0.0f;
m_LoadingSpeed = 1.0f;
m_LoadingSlider.value = 0.0f;
StartCoroutine(AsyncLoading());
}
IEnumerator AsyncLoading()
{
m_AsyOperation = SceneManager.LoadSceneAsync(SceneDefine.SCENE_ID_MAIN_SCENE);
m_AsyOperation.allowSceneActivation = false;//阻止加载完成自动切换
yield return m_AsyOperation;
}
private void Update()
{
m_LoadingProgress = (m_AsyOperation.progress >= 0.9f) ? 1.0f : m_AsyOperation.progress; //operation.progress的值最大为0.9
if (m_LoadingSlider.value < m_LoadingProgress)
{
m_LoadingSlider.value = Mathf.Lerp(m_LoadingSlider.value, m_LoadingProgress, Time.deltaTime * m_LoadingSpeed);
if(Mathf.Abs(m_LoadingSlider.value - m_LoadingProgress) < 0.01f)
{
m_LoadingSlider.value = m_LoadingProgress;
}
}
if ((int)(m_LoadingSlider.value * 100) == 100)
{
//允许异步加载完毕后自动切换场景
m_AsyOperation.allowSceneActivation = true;
}
m_LoadingText.text = ((int)(m_LoadingSlider.value * 100)).ToString() + "%";
}
}
其实这里比较重要的就是AsyncOperation类,可以通过这个类方便的知道某个异步加载协程的进度。
(需要注意的是AsyncOperation.progress的最大值是0.9)
这样我们运行游戏时在LoginScene,在这个场景触发某个事件后,直接转入TransitionScene,在这个场景里做下一个主场景MainScene的异步资源加载,当资源加载完毕后就切换到真正的场景MainScene。