单例模式
一种和static方法较为类似的东西。
下面两种写法的作用类似:
public class Config
{
public static int a;
public static void F(){};
}
// 调用
Config.a;
Config.F();
public class Config
{
private Config() { }
public static readonly Config instance = new Config();
public int a;
public void F(){};
}
// 调用
Config.instance.a;
Config.instance.F();
单例模式相当于全局性只有一个实例,通过这个实例来调用成员。
场景切换(A to B)
场景切换的时候,会销毁当前场景的资源,并加载目标场景的资源。当目标场景资源量较大的时候,加载的进度会非常缓慢。
而此时原场景已经销毁,所以加载的过程会持续黑屏。为了提升用户体验,我们加入Loading界面。
- 首先,Loading场景和当前场景是两个场景,所以我们需要用一个全局变量来存储要加载的场面名称。可以用PlayerPrefs或者单例模式或者静态类来存储,都可以。
- 再次强调所有可能加载的场景都需要在生成设置里面,加入Build场景。
- 由于Loading场景一般资源比较少,所以直接在A场景通过
SceneManager.LoadScene("Loading")
加载Loading场景
Loading场景
- 先通过全局变量获取到要跳转的场景
- 异步Load需要协程,所以
StartCoroutine(StartLoadingScene)
- 在StartLoadingScene内加载场景
AsyncOperation op = SceneManager.LoadSceneAsync(Config.instance.sceneToLoad);
- 此时,为了让Loading界面不单调,一般可以加个进度条。加载的进度在op.progress,从0到1,当等于1时表明加载结束
进度条步骤
- 我们在Loading里面加个Slider
- 在Start内获取Slider并每一帧修改其value属性。
- 我这里是进度条从100到0,你们自己看着改下就行。
public float processValue;
GameObject slider;
void Start()
{
slider = transform.Find("Slider").gameObject;
StartCoroutine(StartLoadingScene());
}
void Update()
{
Debug.Log(processValue);
slider.GetComponent<Slider>().value = 1 - processValue;
}
- 在
StartLoadingScene
内部时时修改processValue
- 下面的版本是加了动画优化的(op.progress跳跃幅度大,可能直接从0.1变到0.9),代码意思大致是每一帧所改变的显示进度最多为0.03(3%),当然这个速度还是很快的,一秒这么多帧。
IEnumerator StartLoadingScene()
{
float maxSpeed = 0.03f;
AsyncOperation op = SceneManager.LoadSceneAsync(Config.instance.sceneToLoad);
// 禁止载入后自己切换
op.allowSceneActivation = false;
// isDone后再加载最后的10%
while (op.progress < 0.9f)
{
// 连续加载
while (processValue < op.progress)
{
processValue += maxSpeed;
yield return new WaitForEndOfFrame();
}
}
while (processValue < 1)
{
processValue += maxSpeed;
yield return new WaitForEndOfFrame();
}
op.allowSceneActivation = true;
}
完整代码
public class LoadingController : MonoBehaviour
{
public float processValue;
GameObject slider;
void Start()
{
slider = transform.Find("Slider").gameObject;
StartCoroutine(StartLoadingScene());
}
void Update()
{
Debug.Log(processValue);
slider.GetComponent<Slider>().value = 1 - processValue;
}
IEnumerator StartLoadingScene()
{
float maxSpeed = 0.03f;
AsyncOperation op = SceneManager.LoadSceneAsync(Config.instance.sceneToLoad);
// 禁止载入后自己切换
op.allowSceneActivation = false;
// isDone后再加载最后的10%
while (op.progress < 0.9f)
{
// 连续加载
while (processValue < op.progress)
{
processValue += maxSpeed;
yield return new WaitForEndOfFrame();
}
}
while (processValue < 1)
{
processValue += maxSpeed;
yield return new WaitForEndOfFrame();
}
op.allowSceneActivation = true;
}
}