Shahriyar
Shahriyar

Reputation: 1583

Unity3D GUI Controls creates two of themselves

I have a code that show users a Yes/No question that they really would like to quit game or not.Here is my code :

using UnityEngine;
using System.Collections;

public class UserPrompt : MonoBehaviour {

public int count = 0;
public bool paused = false;

public static UserPrompt Instance;


// Use this for initialization
void Awake ()
{
    if (Instance == null)   
    {   
        Instance = this;    
    }
}

// Update is called once per frame
void Update () 
{
    if (Input.GetKeyDown(KeyCode.Escape))
    { 
        paused = true;
        count = 1;
    }

    if(paused)
        Time.timeScale = 0;
    else
        Time.timeScale = 1;
}

void OnGUI ()
{
    if(count == 1)
    {
        GUI.Box(new Rect(0,0,Screen.width,Screen.height),"Exit");
        GUI.Label(new Rect(Screen.width*1/4,Screen.height*2/6,Screen.width*2/4,Screen.height*1/6), "Do you really want quit to main menu ?");
        if(GUI.Button(new Rect(Screen.width/4,Screen.height*3/8,Screen.width/2,Screen.height/8),"Yes")) 
            Application.LoadLevel("Menu");

        if(GUI.Button(new Rect(Screen.width/4,Screen.height*4/8,Screen.width/2,Screen.height/8),"Keep Playing"))
        {
            paused = false;
            count = 0;
        }
    }
}
}

The problem is that i should click on "Keep Playing" button twice to disappear, it seems that this codes creates twice of each GUI object but i can't see whats wrong.

Thanks in advance

Upvotes: 1

Views: 169

Answers (2)

Happy Apple
Happy Apple

Reputation: 746

Wow, what complete overkill.

  1. A 'singleton' implementation that doesn't actually persist one active copy of the script in scene
  2. Unnecessary attempt at 'singleton' pattern when the script is entirely self-regulating. All methods are called as part of the typical engine updates.
  3. Use of 'count == 1' to ensure only one active set of GUI instructions in a script that's supposed to be singleton.

Quick solution

The really laziest solution to enforce one active GUI per scene, regardless of how many scripts, is to simply tear out the current Instance variable and make Count private static instead.

Robust solution

You don't need the Count property at all.

If you're interested in a more robust singleton MonoBehaviour component, consider something like this:

private static UserPrompt _instance;
public static UserPrompt Instance 
{
    get
    {
        if (_instance != null)
            return _instance;

        _instance = (UserPrompt )FindObjectOfType(typeof(UserPrompt));

        if (_instance != null)
            return _instance;

        GameObject newObject = new GameObject();
        _instance = newObject.AddComponent<UserPrompt>();

        newObject.name = "UserPrompt";

        if (_instance == null)
            throw new NullReferenceException("Cannot instance UserPrompt");

        return _instance;
    }
}

That works if you plan on calling the script into existence when you reference it, like UserPrompt.Instance - it assumes there's one in the scene, else it'll create one for you to reference. However you can still accidentally have multiple UserPrompts in the scene with this, so consider also:

private void
    OnEnable()
{
    if (_instance == null || !_instance.enabled)
    {
        _instance = this;
    }
    else
    {
        enabled = false;
    }
}

private void
    OnDisable()
{
    if (this == _instance) _instance = null;
}

If a new UserPrompt appears in the scene, it will check that there's no active instance, else disable itself. Disabling is preferential to DestroyImmediate(this), which will probably throw a NullReferenceException in the editor. Ofcourse you can choose to simply catch the Exception.

Upvotes: 1

Alfonso Nava
Alfonso Nava

Reputation: 147

Check if the script is not used in 2 objects, you could also check this by adding a label that will show, this.parent.name, it will show the GO who use the scripts.

Upvotes: 1

Related Questions