2019-11-28 DontDestroyOnLoad与单例

首先渣翻一下官方解释与示例吧~

Object.DontDestroyOnLoad 加载时不销毁


public static void DontDestroyOnLoad(Object target);

Parameters 参数

target An Object not destroyed on Scene change.
目标对象 目标对象是当场景变化的时候不会销毁的对象

Description 描述

Do not destroy the target Object when loading a new Scene.
加载场景的时候,不会销毁目标对象。

The load of a new Scene destroys all current Scene objects. Call Object.DontDestroyOnLoad to preserve an Object during level loading. If the target Object is a component or GameObject, Unity also preserves all of the Transform’s children.Object.DontDestroyOnLoad does not return a value.

在加载新场景的时候,所有当前场景内的对象都会被销毁掉。调用Object.DontDestroyOnLoad可以在新场景加载时保留一个目标对象。如果目标对象是一个组件或者是一个GameObject,Unity还会保留其所有的子物件。Object.DontDestroyOnLoad是一个void函数,不会有返回值。

To implement this example, create two new Scenes, named scene1 and scene2. Open scene1 and add the SceneSwap.cs script to an empty GameObject and name it Menu. Next, add DontDestroy.cs to a new GameObject and name it BackgroundMusic. Add an AudioSource to BackgroundMusic - Add Component > Audio > Audio Source - and import an AudioClip into your Project. Assign the AudioClip to the AudioSource’s AudioClip field. Create a tag, call it music, and add it to BackgroundMusic. Switch to scene2. Again add SceneSwap.cs to a new GameObject and name it Menu. Save the Project. Return to scene1 and run the Project from the Editor.

1.我们创建两个新的场景来实现此示例,名为scene1和scene2。 打开scene1并将SceneSwap.cs脚本添加到一个空的GameObject并将其命名为Menu。

2.接下来,将DontDestroy.cs添加到新的GameObject中,并将其命名为BackgroundMusic。 将AudioSource添加到BackgroundMusic:Add Component > Audio > Audio Source,并导入一个AudioClip到项目中(可理解为声音文件)。 将声音文件分配到AudioSource的AudioClip字段。 创建一个tag,命名为Music,并将其添加到BackgroundMusic。

3.切换到场景2。 再次将SceneSwap.cs添加到新的GameObject并将其命名为Menu。 保存项目。 返回场景1并从编辑器中运行项目。

SceneSwap.cs 脚本:

using UnityEngine;
using UnityEngine.SceneManagement;

// Object.DontDestroyOnLoad example.
//
// Two scenes call each other. This happens when OnGUI button is clicked.
// scene1 will load scene2; scene2 will load scene1. Both scenes have
// the Menu GameObject with the SceneSwap.cs script attached.
//
// AudioSource plays an AudioClip as the game runs. This is on the
// BackgroundMusic GameObject which has a music tag.  The audio
// starts in AudioSource.playOnAwake. The DontDestroy.cs script
// is attached to BackgroundMusic.

public class SceneSwap : MonoBehaviour
{
    private void OnGUI()
    {
        int xCenter = (Screen.width / 2);
        int yCenter = (Screen.height / 2);
        int width = 400;
        int height = 120;

        GUIStyle fontSize = new GUIStyle(GUI.skin.GetStyle("button"));
        fontSize.fontSize = 32;

        Scene scene = SceneManager.GetActiveScene();

        if (scene.name == "scene1")
        {
            // Show a button to allow scene2 to be switched to.
            if (GUI.Button(new Rect(xCenter - width / 2, yCenter - height / 2, width, height), "Load second scene", fontSize))
            {
                SceneManager.LoadScene("scene2");
            }
        }
        else
        {
            // Show a button to allow scene1 to be returned to.
            if (GUI.Button(new Rect(xCenter - width / 2, yCenter - height / 2, width, height), "Return to first scene", fontSize))
            {
                SceneManager.LoadScene("scene1");
            }
        }
    }
}

DontDestroy.cs 脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Object.DontDestroyOnLoad example.
//
// This script example manages the playing audio. The GameObject with the
// "music" tag is the BackgroundMusic GameObject. The AudioSource has the
// audio attached to the AudioClip.

public class DontDestroy : MonoBehaviour
{
    void Awake()
    {
        GameObject[] objs = GameObject.FindGameObjectsWithTag("music");

        if (objs.Length > 1)
        {
            Destroy(this.gameObject);
        }

        DontDestroyOnLoad(this.gameObject);
    }
}

那么这段代码是什么意思呢?
就是在两个场景scene1scene2各自设了两个按钮,点击各自的按钮就切换到下一个场景中。
游戏运行时,AudioSource会播放一个AudioClip。 这是因为具有music的tag的背景音乐GameObject(BackgroundMusic)里有播放组件。 由于DontDestroy.cs脚本附加到BackgroundMusic,所以切换场景的时候BackgroundMusic不会被清除,而是留到了下一个场景中。


那么这样又会带来一个问题,由scene2重新回到scene1的BackgroundMusic,会与新场景中的BackgroundMusic重复,随着多次切换,会有很多的BackgroundMusic出现。

上面的例子给的解决方案是利用具有music的tag的Gameobject数量,让其具有唯一性。
本文给出一种利用单例的方法,也可以满足唯一性。
为BackgroundMusic添加MusicController.cs脚本

/// 
/// background music in game
/// 
public class MusicController : MonoBehaviour {

    public static MusicController Music;
    public AudioSource audiosource;
    public AudioClip[] MusicClips;

    void Awake()
    {
        if (Music == null)
        {
            DontDestroyOnLoad(gameObject);
            Music = this;
        }
        else if (Music != this)
        {
            Destroy(gameObject);
        }

这样切换场景时如果有重复的出现,作为static静态变量的类本身的单例,是一定存在的,这样就直接删掉了新场景中的BackgroundMusic。

你可能感兴趣的:(2019-11-28 DontDestroyOnLoad与单例)