Search Unity

Button disable by default

Discussion in 'Getting Started' started by Mister_Pyxel, May 8, 2017.

  1. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Hi everyone,

    I have some trouble dealing with buttons, I was trying to create an high score and displaying it in my game (which is the survival shooter tutorial in which I keep try new thing) as shown in this tutorial:


    Everything work perfectly, the high score work, update itself and all.
    Then I have try to create a "Reset High Score" button, so I created it, I placed it, and I updated the script but it doesn't work.

    After some test I have see that in fact, it is disable, and I don't know how to enable it.
    I have look on internet and I have found multiple things, so as I may have unchecked something to check or some error like this, here are some elements:

    I have my EvenSystem, his inspector look like this:
    upload_2017-5-8_15-22-56.png

    My button's inspector look like this
    upload_2017-5-8_15-23-24.png

    I have a graphic RayCast in my canvas:
    upload_2017-5-8_15-24-10.png

    I have disable the RayCast target on the text over the button so it don't block it:
    upload_2017-5-8_15-24-30.png


    And InGame my button look like this:
    upload_2017-5-8_15-25-3.png

    The color is the one I have set on "Disable color", so I think my problem is that it is disable and I don't know how to enable it.
    (Note that the button is inactive all the game and with an animation it become active when the player die, I don't know if this can create problems)

    Do somebody know where is the problem?

    Thanks for reading this!
     
  2. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    You can use Button.interactable to set the interactability of the button at runtime:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class ButtonController : Monobehaviour {
    7.  
    8. Button button;
    9.  
    10.     void Start () {
    11.         button = GetComponent<Button>();
    12.         button.interactable = false;
    13.         }
    14.  
    15.     void Update() {
    16.         bool something;
    17.         if (something == true) {button.interactable = true}
    18.         else {button.interactable = false}
    19.         }
    20. }
    Note that the above is just an example - I'm not a huge fan of putting anything into the Update() function if I can avoid it. A cleaner solution would be to subscribe the script above to an event that fires off whenever the button should become interactable - this way, you can decouple the logic from the UI. However, the above should work as a quick-and-dirty fix.
     
    Last edited: May 8, 2017
  3. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Thanks, this should work, but where do I have to put this script? In my canvas or in my button directly?
     
  4. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    You can attach it directly to the Button - but do remember that you still have to find a way to manipulate the value of the bool something. :)

    The script above - unless I got the syntax wrong somewhere - should disable the button at the start of your game and then enable it only when something is set to true.

    Good luck!
     
  5. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Okey, yes I think I see how to do it (I have a GameOverManager script and I think I can just creat another function out of void start in the Button script that will activate the button, and call it when the game is over).

    Thank you verry much for your help!
     
    Last edited: May 8, 2017
  6. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    I have try your solution, but I have integrated part of your script directly in my GameOverManager.
    But this still don't work, I have also reactivate the button at the begining of the game (as the script should uncheck the "Interactable" case and the script work because I see in the inspector that the case unchek itself at the begining and come back at the Game Over, but the button still have the color set on the "Disable Color" line.
    So I still can't click the button :(
     
  7. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Have you tried debugging it? Without seeing the script, the thing I'd want to know the most is whether the instruction to activate / deactivate the button "reaches" the script or not. Add the debug.log lines (as below) and see whether the messages even appear in the console and, if yes, whether they appear under the right conditions. If they do, then at least we know that the logic is correct and something else is the culprit.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class ButtonController : Monobehaviour {
    7.    
    8. Button button;
    9.  
    10.     void Start () {
    11.         button = GetComponent<Button>();
    12.         button.interactable = false;
    13.         Debug.Log("Button has been disabled via the script!");
    14.         }
    15.    
    16.     void Update() {
    17.         bool something;
    18.         if (something == true)
    19.             {
    20.             button.interactable = true;
    21.             Debug.Log("The button has been enabled via the script!");
    22.             }
    23.         else
    24.             {
    25.             button.interactable = false;
    26.             Debug.Log("The button is remaining disabled via the script!");
    27.             }
    28.         }
    29. }
     
  8. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Okey I just tryed it and the Debug lines apear, so the script seem to work well
     
  9. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Right, that's good. You mentioned that you integrated the script into the GameOverManager script. Could you post it here, please? Chances are, something's wrong with setting the condition for re-activating the button (e.g., modifying the value of the something bool).
     
  10. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Okey, here is the script:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using UnityEngine.Events;
    5.  
    6. public class GameOverManager : MonoBehaviour
    7. {
    8.     public Button button;
    9.     public GameObject buttonObject;
    10.     public PlayerHealth playerHealth;
    11.     public Text gameOverText;
    12.     public Text highScoreText;
    13.  
    14.     Animator anim;
    15.  
    16.     private void Start()
    17.     {
    18.         button = buttonObject.GetComponent<Button>();
    19.         button.interactable = false;
    20.         Debug.Log("The button is disabled via the script!");
    21.         highScoreText.text = "High Score: " + PlayerPrefs.GetInt("HighScore", 0).ToString();
    22.     }
    23.  
    24.     void Awake()
    25.     {
    26.         anim = GetComponent<Animator>();
    27.     }
    28.  
    29.     void Update()
    30.     {
    31.         if (ScoreManager.score > PlayerPrefs.GetInt("HighScore", 0))
    32.         {
    33.             PlayerPrefs.SetInt("HighScore", ScoreManager.score);
    34.             highScoreText.text = "High Score: " + PlayerPrefs.GetInt("HighScore", ScoreManager.score).ToString();
    35.         }
    36.  
    37.         if (playerHealth.currentHealth <= 0)
    38.         {
    39.             gameOverText.text = "Game Over";
    40.             button.interactable = true;
    41.             Debug.Log("The button is enabled via the script!");
    42.             anim.SetTrigger("GameOver");
    43.         }
    44.     }
    45.  
    46.     public void Reset ()
    47.     {
    48.         PlayerPrefs.DeleteKey("HighScore");
    49.         highScoreText.text = "High Score: 0";
    50.         Debug.Log("Boutton pressé");
    51.     }
    52. }
    53.  
    If you have questions about the code tell me, I have delete them as I didn't do them in english :D
     
  11. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    I speak about the comments in the code here (but I don't know why, the site don't want me to edit this :confused:)
     
  12. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    What is buttonObject? You don't need to attach a button to a gameObject in order for it to function. When you create a button using Unity's UI, it adds RectTransform, an Image, and a Button component, for example:

    --- Button
    ----- Text

    As opposed to:

    --- buttonObject
    ----- Button
    ------- Text

    In the above case, what is your Button component attached to - the buttonObject or the Button?

    Also, since you're anyway making use of public variables, you can simply drag the Button component - as opposed to buttonObject - into the Button slot in the inspector. Then you won't need to make use of GetComponent at all and can safely comment it out.
     
  13. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    This is what I have done first but this gave me an error, and by looking up on internet I have see that the error was coming from the fact that my button element didn't have any gameobject attach to it.
    Okey so I do it like it was before, the error was:
    NullReferenceException: Object reference not set to an instance of an object
    GameOverManager.Start () (at Assets/Scripts/Managers/GameOverManager.cs:18)


    And the line 18 in my script is this: button.interactable = false;
     
  14. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Actually, no. The error you were receiving had nothing to do with there not being a gameObject and everything to do with Unity being unable to find the Button component in the location where you told it to look for it.

    Right now, in your script, which gameObject is the Button component attached to - buttonObject or Button? E.g.,:

    This:

    --- Button<Button>
    ----- Text

    Or this?

    --- buttonObject<Button>
    ----- Button
    ------- Text
     
  15. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    In the script I have this:
    button = buttonObject.GetComponent<Button>();

    So the variable "button" take the button component from the button GameObject.
     
  16. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Right - and there's the problem. The Button component should be attached to the Button game object (that is, the one that has text as its child) and not to objectButton (which has the Button as its child) . As it is, you are basically changing to false the interactability of an empty game object (buttonObject) that likely does not have interactable parts to begin with.

    So, here's what you do:
    1. Get rid of buttonObject altogether - it serves absolutely no purpose - so that you only have Button and Text, rather than buttonObject, Button, and Text
    2. Make sure that the remaining Button object has the <Button> script attached to it
    3. Drag the Button gameobject to the public Button slot in the inspector - that will make it pick up the Button component
    4. Delete the button = buttonObject.GetComponent<Button>(); line - you won't need it since you're relying on the Inspector's drag-and-drop functionality
    This should work - let me know.
     
  17. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Okey, I understand what you mean, I was thinking that I was needing the "GetComponent" part but no.
    So I have do what you have tell me and no error occured (which is a good point in my opinion).
    But still, the button is not clickable:
    upload_2017-5-8_22-25-52.png
    (the green color is still for inactive)

    Even through that the button object is mark as interactable.
    upload_2017-5-8_22-26-51.png

    And is linked to the GameOverManager script:
    upload_2017-5-8_22-27-57.png
    (it's blue because I use blue interface to remind me I'm in play mode)
     
  18. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Let's set aside the color of the button for the moment and rely on what the Debug Log is telling us. I noticed you have a debug log line for the Reset() method which in turn gets called when the button is pressed. Can you please check that a) it is still listed as the OnClick event in the Inspector for the button (remember, we changed a few things) and b) that the text "Boutton pressé" does not appear in the console when you click it in play mode?
     
  19. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Okey, I have check it and it is still in the OnClick part:
    upload_2017-5-8_23-22-3.png
    Is it what it is supposed to look like?

    And when I play, the debug message don't appear when I try to click the button.
     
  20. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Then I honestly don't know what you're doing wrong. If the Button was indeed interactable - as you posted in the screenshot - then the debug message would be appearing in the console. But since it's not appearing, I must conclude that the button is not, in fact, interactable - which runs in direct contradiction with the screenshot.

    Maybe someone else can chime in. Sorry.
     
  21. Mister_Pyxel

    Mister_Pyxel

    Joined:
    May 4, 2017
    Posts:
    47
    Don't worry, and thank you verry much for taking the time to help me!
    It's almost midnight where I am so I will go sleep and try to fix this tomorrow.
    Tank you again, and see you in another thread maybe. :)
     
  22. austinborden

    austinborden

    Joined:
    Aug 5, 2016
    Posts:
    24
    5 years late to reply, but I just had the same issue of not being able to figure out why one of my buttons was getting set to the disabled state when it was still interactable. Turns out I had a Canvas Group attached to a parent GameObject that had interactable set to false! Hard to debug, but something to look for now you know.
     
    Flying_Banana likes this.
  23. Flying_Banana

    Flying_Banana

    Joined:
    Jun 19, 2019
    Posts:
    29
    You just saved me maybe an hour of debugging :')