Question

I want when the button has been clicked, it will show some GUI button on it. I already tried the delegate, but the event is not fired (I mean the GUI button is not shown).

Here is the code that I am using:

The code below is to show the GUI button when I run the game.

public class IItemDatabase : MonoBehaviour
{
    public delegate void Action(); // Set the event for the button

    public static event Action onClicked; // The event for when the button has been clicked

    protected virtual void OnGUI()
    {
        // Call the SetStyle method
        SetStyle();

        // Set the GUIContent as the tooltip
        GUIContent buttonText = new GUIContent("Open Shop");

        // Set the GUIContent as the tooltip
        GUIContent buttonTexts = new GUIContent("Open Inventory");

        // This GUILayoutUtility is useful because it is to fit the content
        Rect buttonGUI = GUILayoutUtility.GetRect(buttonText, "Button");

        // This GUILayoutUtility is useful because it is to fit the content
        Rect buttonGUIs = GUILayoutUtility.GetRect(buttonTexts, "Button");

        // Set where have to the Rect displayed
        buttonGUI.x = 5;
        buttonGUI.y = Screen.height - 25;

        // Set where have to the Rect displayed
        buttonGUIs.x = 125;
        buttonGUIs.y = Screen.height - 25;

        // If the button has been clicked

        if (GUI.Button(buttonGUI, buttonText, style))
        {
            if (onClicked != null)
            {
                onClicked();
            }
        }

        if (GUI.Button(buttonGUIs, buttonTexts, style))
        {
            if (onClicked != null)
            {
                onClicked();
            }
        }

        // End of the clicked button event
    }
}

And here is the I want it to display when the button has been clicked:

public class IInventory : MonoBehaviour 
{

    protected virtual void OnEnable()
    {
        IItemDatabase.onClicked += DoGUI;
    }

    protected virtual void OnDisable()
    {
        IItemDatabase.onClicked -= DoGUI;
    }

    protected virtual void DoGUI()
    {
       Rect slotRect = new Rect(x * 35 + (Screen.width / 3) + 50, y * 35 + (Screen.height / 3) - 10, 30, 30);
                GUI.Box(slotRect, GUIContent.none);
    }
}

But when I clicked the button that it suppose to fired the DoGUI() in IInventory class, it does not run the function.

How do I solve this?

Thank you.

Your answer much appreciated!

Was it helpful?

Solution

Your problem is not the event or the delegate, but a misunderstanding on how OnGUI() works.

The OnGUI() method might be called several times per frame, but your onClicked event will only be called once after you clicked the button. So your Inventory is only visible for a few milliseconds.

There are several ways to solve the problem. Your goal is to call DoGUI() during every OnGUI() call as long as you want the inventory to be shown. You could introduce a boolean that saves the state of the inventory menu and decides whether the menu should be visible or not. If you want your Open Inventory button to toggle the menu, you could try something like that

public class IItemDatabase : MonoBehaviour
{
    public static event Action onClicked; // The event for when the button has been clicked

    private bool showInventory = false;

    protected virtual void OnGUI()
    {
        // I removed your other code to simplify the example

        if (GUI.Button("Open Inventory"))
        {
            // toggle the status
            showInventory = !showInventory
        }

        if (showInventory && onClicked != null)
        {
            onClicked();
        }

    }
}

If you want to keep the event depends on your application. If you keep it, I would rename it to showInventoryGUI or something similar to better reflect its intention. On the other hand you could simply remove the event and just call the method IInventory.DoGUI() directly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top