Search Unity

[SOLVED] Changing UI Image with Script

Discussion in 'UGUI & TextMesh Pro' started by CelticKnight, Nov 9, 2016.

  1. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    Hello Guys,

    I have run into a problem that I am hoping that you maybe able to help with.

    I'll try and be as specific as I can but remember I have had a large break from using Unity - really long - and trying to get back into it slowly by doing a course and trying to add things as I think of them to the stock project.

    Right, I have a canvas and on this canvas I have a number of item a couple of Image Items and a Scrolling Text box with a script attached and a child object acting as a mask so the text scrolls properly. On the Scrolling box there is a script that control the game actions - basically just key presses and a really, really basic state engine. So if you press a certain button it changes the state.

    Now, I would like to be able to change the image that is shown in one of the Image Boxes, that is dependent on the state. and I have absolutely no idea how this might be done

    I did create another image box with a script that scrolls though a number of images (sprites) when you press a specific key, however, that doesn't link up at all with the game action script or whether that would even work for my purposes. I did try but I just don't know enough.

    Any help, tips, hints pointer on what I should be doing would be greatly appreciated.

    Thankyou in advance,
    CK.
     
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,689
    It should be as simple as calling "SetActive()" on the objects you want to enable / disable.
    Or you could have toggles and attach the OnClick event with a dynamic bool to the "Active" state of the images.
     
  3. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    Thankyou for replying but I don't really understand what you are trying to say - after a long time in the martial arts I have just about forgotten everything to do with Unity - probably a result of being thrown too much or hits to the head. I don't really know how to set toggles or an OnClick event.

    So this is the code I am trying to use to follow the states and get the image working. I only have one of the states encoded in this code snippet. Sorry for all the comments - at the moment I need them!

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class TextController : MonoBehaviour {
    6.  
    7.     //we all making a public item of type Text with the name "text"
    8.     //making it public allows all functions here to see it - probably outside
    9.     //this class as well??
    10.     //This will allow us to programatically put text into the TextBox vai text :)
    11.     //    UI element
    12.     public Text text;
    13.  
    14.     //public links to images
    15.     //albiet in this script and not accessing the other "script" class
    16.     //that does in a sense work
    17.     public Sprite prisonGuard;
    18.     public Sprite prisonBed;
    19.     public Sprite prisonCorridor;
    20.     public Sprite prisonStairs;
    21.  
    22.     //Use an enum to track states - ie the room we are in and what we have -sort of
    23.     //keep it private does not need to be accessed outside this method/class
    24.     private enum game_States{     cell,sheets_0,mirror,lock_0,
    25.                                 sheets_1,cell_mirror,lock_1,freedom,
    26.                                 corridor_0, stairs_0,floor,closet_door,courtyard_capture,
    27.                                 corrider_1};
    28.     private game_States myState;
    29.  
    30.     //to change size of TextBox
    31.     //needs to have a value added to it to make it expand a little more
    32.     //  than the size specified so I've added 250 to the value ala:
    33.     //    rt.sizeDelta = new Vector2(rt.rect.width, height1+250);
    34.  
    35.     RectTransform rt;
    36.  
    37.     //Access the ImageBox
    38.     public Image imageLinker;
    39.  
    40.  
    41.     // Use this for initialization
    42.     void Start () {
    43.         //trying something a little funky here
    44.         rt = gameObject.GetComponent<RectTransform>();     // Acess the RectTransform
    45.         text = gameObject.GetComponent<Text>();         // Accessing the text component
    46.  
    47.         myState = game_States.cell;
    48.  
    49.         //ACess the image box here
    50.         imageLinker = gameObject.GetComponent<Image> ();        // Access the imageBox
    51.  
    52.         print ("myState: "+myState);
    53.         //reset textbox height?!?!  For scrolling purposes
    54.         //rt.sizeDelta = new Vector2(rt.rect.width, text.preferredHeight+250);
    55.     }
    56.  
    57.     // Update is called once per frame
    58.     void Update () {
    59.  
    60.         //the code to keep track of where the player is - ie the state
    61.         //all the if's and else ifs
    62.         if        (myState == game_States.cell)        {state_cell ();}
    63.         else if(myState == game_States.sheets_0)    {state_Sheets_0 ();}
    64.         else if(myState == game_States.sheets_1)    {state_sheets_1 ();}
    65.         else if(myState == game_States.lock_0)        {state_lock_0 ();}
    66.         else if(myState == game_States.mirror)        {state_mirror ();}
    67.         else if(myState == game_States.cell_mirror)    {cell_mirror ();}
    68.         else if(myState == game_States.lock_1)        {state_lock_1 ();}
    69.         else if(myState == game_States.corridor_0)    {state_corridor_0();}
    70.         else if(myState == game_States.stairs_0)    {state_stairs_0();}
    71.         else if(myState == game_States.courtyard_capture)    {state_courtyard_capture();}
    72.         else if(myState == game_States.floor)        {state_floor();}
    73.         else if(myState == game_States.corrider_1)    {state_corridor_1();}
    74.         //else if(myState == game_States.closet_door)    {state_closet_door();}
    75.         //end the block if and else if's
    76.  
    77.     }//-->End Update() method
    78.  
    79.     void state_cell(){
    80.         print ("State: " + myState);
    81.  
    82.         text.text =    "\nYou are in a Prison cell and you wish to escape.  There are " +
    83.                     "some dirty sheets on the bed, a mirror on the wall and a " +
    84.                     "door that is locked from the outside." +
    85.                     "\n\n(Press S to view Sheets, M to view Mirror, L to view Lock)";
    86.      
    87.         //Error testing porpoises
    88.         rt.sizeDelta = new Vector2(rt.rect.width, text.preferredHeight+250);    //x,y
    89.  
    90.         GetComponent<Image> ().sprite = prisonCell;
    91.  
    92.  
    93.         //respond to key presses here
    94.         if (Input.GetKeyDown (KeyCode.S))         {myState=game_States.sheets_0;}
    95.         else if (Input.GetKeyDown (KeyCode.L))    {myState=game_States.lock_0;}
    96.         else if (Input.GetKeyDown (KeyCode.M))    {myState = game_States.mirror;}
    97.      
    98.     }//end state_cell
    99.  
    And here is an image showing how everything is linked up in the script in relation to the Public variables:



    Does that explain better what I am trying to do and how basic I am at Unity:). Lines 50 and 90 are the ones, that try to at least, access the ImageBox and set the sprite.

    Thankyou in Advance,
    CK.
     
    hopetolive and EliasFazel like this.
  4. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    Is there anything that I can add to this question to help facilitate an answer? Like a screenshot of the heirarchy? Or, at least find out if it's possible, impossible to do, or, if I have gone about it all wrong and should forget about it for the meantime?

    Anything really would help!

    Thanks in Advance,
    CK.
     
  5. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    From your overwhelming silence on this matter, I take it that it is impossible to change/update a UI Image from another UI component :(. Anyway, I hope to be able to do something like this somehow in the future so I can complete this little project in a way I think it should be done. Even the guy who made the course suggested adding images in some way but doesn't discuss this until later in the course - well that is what he said, I hope he does.

    Anyway, thankyou to all who took the time to read my question.

    Regards,
    CK.
     
    Last edited: Nov 13, 2016
  6. Nicholas1010

    Nicholas1010

    Joined:
    Aug 2, 2014
    Posts:
    20
    If I understand correctly and unless you are looking for something else, to answer your question simply, I did this:

    Attached event trigger to image and made PointerClick event:



    Then I made example script that changes sprites (of dog, deer and frog :D) on different clicks with a function attached to that event trigger.

    It uses switch to increment number that determines which image/sprite gets displayed

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using System.Collections;
    5.  
    6. public class Example : MonoBehaviour {
    7.  
    8.     public Sprite dogImg; // I attched these from editor
    9.     public Sprite frogImg;
    10.     public Sprite deerImg;
    11.  
    12.     public int imgNumberCount;
    13.  
    14.  
    15.     public void changeImages() // make sure to attach this to event trigger
    16.     {
    17.         switch (imgNumberCount)
    18.         {
    19.  
    20.             case 0:
    21.                 GetComponent<Image>().sprite = dogImg;
    22.                 imgNumberCount++; //increase count so it gets higher and switches to different sprite
    23.                 break;
    24.             case 1:
    25.                 GetComponent<Image>().sprite = frogImg;
    26.                 imgNumberCount++;
    27.                 break;
    28.             case 2:
    29.                 GetComponent<Image>().sprite = deerImg;
    30.                 imgNumberCount++;
    31.                 imgNumberCount = 0; //Reset it to 0
    32.                 break;
    33.             default:
    34.                 Debug.Log("Error");
    35.                 break;
    36.         }
    37.     }
    38. }
    39.  
    40.  


    Result:



    I may not have used best practices, so sorry if I did not. But I hope this answer suits your needs, if not, tell me and I may try to correct it.
     
  7. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    Sorry for such a late reply I had to give an impromptu lesson for some students who are grading soon and was a bit sore and sorry afterwards - I wanted to make sure they know the material. Now onto the topic at hand, when I first had the idea of adding image to the project I made an image box in the canvas attached a script and did almost the same thing as you. The problem occurred when I tried using another UI Image box that linked up to the TextController script in another UI element - is this case a UI Text box.

    I tried some different things since I posted the above and found that the ImageLinker (ie the UI Image box) is a null. In the TextController script I used:

    Code (CSharp):
    1. // Access the imageBox
    2. imageLinker = gameObject.GetComponent<Image> ();    
    3. if (imageLinker == null)
    4.        print ("wtf.............");
    And "WTF" was duly printed to the console

    and using the code in a further Text Controller function to change the image:

    Code (CSharp):
    1. imageLinker.GetComponent<Image> ().sprite = prisonBed;
    Results in the error: NullReferenceException: Object reference not set to an instance of an object

    So I'm stumped - I can't think of anything else I can do. Can you think of anything I might be able to try?

    Regards,
    CK.
     
    alexrau likes this.
  8. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    imageLinker = gameObject.GetComponent<Image> ();

    That line assumes you have the Image on the same object as whatever this script is attached to. If these aren't on the same gameobject, then you'll get null, which is what you are getting. You need a reference to the gameobject that has your Image on it and need to target it.
     
  9. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    It's definitely not the same object, completely different UI components. The script is on the text UI component and the image I wish to display is on another Image component - on the same canvas though. But I thought the targeting, as you call it, was established by the process below, where I have the image component being pointed to as well as all the images (sprites) I wish to display, there are more of course, but, this is to get it started.



    Or, do I have a fundamental misunderstanding of the targeting process?

    I have been thinking of ditching the UI Image Components and just displaying a single sprite image in the scene, and then replacing it when another sprite when a new state has been reached. Would that be a better idea?
     
  10. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    If you have a public variable that you drag and drop into, but then in your script you have this
    imageLinker = gameObject.GetComponent<Image> ();

    You now overwrite the variable. This line tells it to check the gameobject the script is on, look for an image component, and assign that to the variable. Since it doesn't find anything, the value is null.

    Try commenting the line out and see if it helps.
     
    kattiya and CelticKnight like this.
  11. CelticKnight

    CelticKnight

    Joined:
    Jan 12, 2015
    Posts:
    378
    Oh my goodness, you are right! I had no idea about that overwriting the "variable". I am totally shocked! I was positive that it had to be done that way. Whenever I looked at code samples on the Unity docs and looking for help with scripting I was forever seeing GetComponent<whatever>(). Even in the same script I was using GetComponent<Text>() and GetComponent<RectTransform>() but as you rightly pointed out they were already on the GameObject

    Without that line the Inspector didn't change the ImageLinker value to: None. It didn't return a Null value, and the sprite DID change.

    So, thankyou greatly for responding and persevering with me, even though I thought I had everything correct. I will now be able to finish this little project the way I envisioned :cool:. And I can't thankyou enough for that!!!

    Warmest Regards,
    CK.
     
    Last edited: Nov 16, 2016
    kattiya and Izzy2000 like this.