Search Unity

How to change button image from another scene

Discussion in '2D' started by StathisGamer, Oct 25, 2019.

  1. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    Hello,
    I have 2 scenes in a unity project and I have a problem that goes like this: In scene1 I have several buttons (each button is a level of the game). In scene2 i have the game and i have created an event (script) that runs when the level is completed. The problem is that i want when that event runs, a specific button of the scene1 to change its image.This is what i have done so far:
    536100d97abfb9b64ebb60acda648e9f.png 3980fcd2a6210411b435d4743bdcf629.png
    Thanks for your time.
     
  2. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    Hi and welcome.

    You probably have to think your game architecture a bit more. You could create a system that stores information about level completion and whatever other data you need. When you complete a level, you store information about the specific level being completed. You need to check how to create a save game system.

    Then, when a menu scene (your scene 10) is loaded, you have a script that will populate/set your buttons so that they reflect the state of your game progress.
     
    vakabaka likes this.
  3. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    Well I will check how to create a save game system but i just want to figure out what im doing wrong in the script i have and how to fix that
     
  4. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    Does anyone else has a solution to this?
     
  5. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    I don't know other solution as Olmi has already said.

    by completed level:
    Code (CSharp):
    1. //not only playerprefs, it can be json, static, dontdestroyonload or whatever
    2. PlayerPrefs.SetInt ("xLevelCompleted", 1);
    in the menu scene:
    Code (CSharp):
    1. void Start() {
    2. //maybe you should check if the value isn't null
    3. if (PlayerPrefs.GetInt ("xLevelCompleted") == 1) {
    4. button.GetComponent<Image>.sprite = levelDoneSprite;
    5. }
    6. }
    7.  
    And, I don't think you can use Start() inside from the OnCollisionEnter
     
    Last edited: Oct 26, 2019
    MisterSkitz likes this.
  6. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    You could set up a static variable: changeButton
    Code (CSharp):
    1. void Start()
    2. {
    3. changeButton = false; // False will represent your default buttons
    4. }
    5.  
    6. void Update()
    7. {
    8. if(changeButton == false)
    9. {
    10. // Set your default buttons up here
    11. }
    12. else{ // Set your new buttons up here }
    13. }
    14.  
    So really when your player enters an OnTriggerEnter or OnCollisionEnter() collider you can easily change the static variable back and forth from true/false, quickly changing the buttons. Although you may not want this to happen until your next scene loads but that's easy to configure. ;)
     
  7. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    If i do that, will it change the buttons sprite on the next scene?
     
  8. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    On your other scene you want to check the status of your static function and IF changeButton == true then load your new buttons. You could run the check inside of a Start() rather than Update() on your other scene. If you don't want a public static variable, then you can use PlayerPrefs. to store the variable:

    Code (CSharp):
    1. // On your scene where buttons determine whether there is a change needed on the other scene
    2. changeButton = true;
    3.  
    4. // Create your storage file ButtonChange and 1 is true 0 is false
    5. // Since it's true in this example it will store the int 1 into changeButton
    6. PlayerPrefs.SetInt("ButtonChange",  (changeButton ? 1 : 0));
    7.  
    8. // On your next scene where you want the buttons to change
    9. if(PlayerPrefs.GetInt("ButtonChange") == true)
    10. {
    11. // Change your button code here
    12. }
    So I didn't test that but I'm like 68% positive that will work as is.
     
  9. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    thanks
     
    MisterSkitz likes this.
  10. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    You're very welcome, amigo! :)
    Let me know how it works out for you and I'm willing to help with any issue that you may encounter.
    One last though, that if you are saving the data for quit game, you may wanna use PlayerPrefs.Save()
    I don't think you need to call this from Application.Quit() but from a checkpoint area within your game. The reason I say this is I think PlayerPrefs stores all variables on quit or crash. I'd like someone more knowledgeable on PlayerPrefs to confirm this though.
     
    vakabaka likes this.
  11. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    So i tried one of the methods above (playerprefs) and for some reason it doesnt work for me and i also get an error :
    -NullReferenceException: Object reference not set to an instance of an object
    -LevelCompleted.Start () (at Assets/LevelCompleted.cs:23)

    these are my scripts that i have used(the 1st is from the game screen and 2nd one is from the level select screen): 3eb16bbef8878cd36d9b41325076a520.png a87e1f6819daf350d2dc8e0d02766356.png ddd292021b7649f010ab631553820bad.png
    If someone can tell me exactly what i need to fix i would be grateful of him! thanks
     
  12. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    button is already Button, don't try to get component "button"
    Edited. Here was something wrong: You can access Image it with button.image

    Code (CSharp):
    1.     public Button button;
    2.     public Sprite LevelDone;
    3.  
    4.     private void Start()
    5.     {
    6.         //not sure, maybe you should check if xLevelCompleted exits and != null
    7.         if (PlayerPrefs.HasKey("xLevelCompleted"))
    8.         {
    9.             if (PlayerPrefs.GetInt("xLevelCompleted") == 1)
    10.             {
    11.                 button.image.sprite = LevelDone;
    12.             }
    13.         }
    14.     }
    and in the levelFinisher switch the lines 17 and 18. Save PlayerPrefs at first and load new level at second.
     
    Last edited: Nov 6, 2019
    MisterSkitz likes this.
  13. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Maybe try

    Code (CSharp):
    1. button.image.sprite = LevelDone;
    You'd wanna check to insure the button isn't null or the sprite.

    Code (CSharp):
    1. button = GetComponent<Button>();
    2.  
    3. if(button != null)
    4. {
    5. button.image.sprite = LevelDone;
    6. if(button.image.sprite == null)
    7. button.image.sprite = LevelDone;
    8. }
    9. else{button = GetComponent<Button>();}
    If this doesn't work then try to make button a public variable. You won't need the GetComponent<Button>() lines anymore. You wouldn't need to check if it's null either. You would only need button.image.sprite = LevelDone;
     
    vakabaka likes this.
  14. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Looks like you beat me to it lol
     
    vakabaka likes this.
  15. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    more answers are always good :)
     
    MisterSkitz likes this.
  16. StathisGamer

    StathisGamer

    Joined:
    Oct 16, 2019
    Posts:
    13
    vakabaka and MisterSkitz thanks so much. I really apriciate that it worked flawlessly. Thanks again!!!!
    ps. It worked but i now have another problem xD now it changes to these sprites whether or not i have done the level... when i enter the level select it just has them

    edit : nvm fixed it thanks anyways
     
    Last edited: Nov 6, 2019
    vakabaka likes this.
  17. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    You have already saved the playerprefs. If you will start new game, then you should reset the value in the playerprefs.

    Code (CSharp):
    1. //set it to something different as 1
    2. PlayerPrefs.SetInt ("xLevelCompleted", 0);
    as example:
    you will reset it every new application start, then somewhere in the gamelogo scene:
    Code (CSharp):
    1. void Start () {
    2. PlayerPrefs.SetInt ("xLevelCompleted", 0);
    3. }
    or you can have a button for the new game:
    then the button will call the loading function and in it add
    Code (CSharp):
    1. public void StartNewGame () {
    2. PlayerPrefs.SetInt ("xLevelCompleted", 0);
    3. //and here load the level
    4. }
    ps. and you can take other name for the value:
    "LevelOne", "FirstLevel", "MySuperBossScene" because you can have other values for the other levels
     
    Last edited: Nov 6, 2019