Unity2D教程:单例模式、SceneManager.LoadSceneAsync场景切换、Loading界面进度条

关注专栏,持续更新哦

教程总目录


单例模式

一种和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;
    }
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/107135042