简体   繁体   中英

Keep Links between two gameObjects when scenes change in unity

I'm Working on a game, and i want to create a mute button. So i wrote a script for that and i attach this script into a gameObject that don't destroy on load.

I link the script with a UI Button present in a main menu. This UI button is destroy when i'm changing scenes.

when i start my game, and i click on the button, the audio turns off, and when i click back, it turns on.

But when i change to another scene, and i go back to the main menu, my script doesn't have the UI Button attach to it. so when i touch the button the audio doesn't change is behavior

I would like to know if it's possible to maintain the link between the UI Button and the script (attach to a normal GameObject), even if the UI Button is destroyed?

i tried this:

ButtonGameObject = GameObject.Find("UI Button");

but it doesn't work.

How can i fix that?

Thanks a lot.

There are many ways to work around this, but here's one:

Step 1: If you haven't already done so, implement a weak singleton pattern on your mute script (let's call it MuteScript.cs for now).

private static MuteScript singleton {get; private set;}
private void Awake() {
    if (singleton == null) singleton = this;
    [whatever other stuff you were already doing in Awake()]
}
public static void ToggleMute(Graphic graphic)
{
    singleton._ToggleMute(graphic);
}
private void _ToggleMute(Graphic graphic)
{
    [whatever code you were running in your original mute method]
}

Step 2: Attach a simple script to your UI button:

public class MuteButton: MonoBehaviour
{
    Graphic myGraphic;
    private void Awake() {
        myGraphic = GetComponent<Graphic>();
    }

    public void OnClick() {
        MuteScript.ToggleMute(myGraphic);
        //I assume you want to do something like change the colour of the button when
        //the player toggles it. Passing the Graphic to the MuteScript is the easiest 
        //way of doing this. If you really want to keep your code clean, though,
        //I recommend expanding the MuteButton class with methods to take care of
        //the UI side of things.
    }
}

Step 3: In Unity Editor, setup your button to call its own OnClick() method, not the MuteScript method.

-

Now when you click the button, it will call the static MuteScript.ToggleMute(), which accesses the static-cached singleton reference, which in turn points back to your original object.

Singletons and static accessors are great for efficiency in Unity because they save you from having to call expensive search functions like FindObjectsOfType(). The only gotcha is that you have to be careful about not having multiple copies of a singleton-class object lying around, especially when using DontDestroyOnLoad().

So a better approach rather than having a script search and grab the component is to use a PlayerPrefs class from Unity. Essentially, it will hold onto all important aspects of the game and auto fill information.

This is a great tool for a lot of user customization aspects of a game. When using this, have a script ( sceneController would be a good name) that will run when the scene starts (create a blank object at 0,0,0) and then under void Start() have the script grab the mute/unmute button: GameObject.Find("MuteButton") or (my favorite) give it a tag called MuteButton and run: GameOject.FindWithTag("MuteButton") . Also once you get a link to the button, add a listener to it for when the button is pressed.

Also store the sound manager in a gameController that will be passed throughout the game. This would control the soundManager and have access to that. So sceneManager will also need a reference to gameManager .

Using a script that is just for player preferences (a controller if you will) is a better way to organize and contain any preferences for the users. Just better clarity and separation.

Example

SceneController Object Script

class SceneController {
    GameObject muteButton;

    void Start() {
        muteButton = GameObject.FindWithTag("muteButton");
        muteButton.AddListener(muteButtonCheck);
    }

    void muteButtonClick() {
        if (PlayerPrefs.GetInt("playerMute")) {
            // If 1 (on)
            // Set sound off
            PlayerPref.SetInt("playerMute", 0);
        } else {
            // It's 0 (off)
            // Set sound on
            PlayerPrefs.SetInt("playerMute", 1);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM