Search Unity

Toggle Canvas UI Image From Seperate Script

Discussion in 'Scripting' started by MadeThisName, Aug 26, 2015.

  1. MadeThisName

    MadeThisName

    Joined:
    Mar 14, 2015
    Posts:
    115
    Ive tried multiple ways and still cant seem to do this. The commented out code is what i have tried as well. Thankyou.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class ToggleVisble : MonoBehaviour {
    6.  
    7.     private GameObject Img;
    8.     //private Image img;
    9.  
    10.     public bool good;
    11.  
    12.     void Start() {
    13.  
    14.         Image Img = GameObject.Find ("/Canvas/Img").gameObject.GetComponent<Image> ();  
    15.         //Image Img = GameObject.Find ("/Canvas/Img").GetComponent<UnityEngine.UI.Image> ();
    16.  
    17.     }
    18.  
    19.     void Update (){
    20.  
    21.         if (!good) {
    22.             Img.SetActive(true);
    23.             //Img.enabled = true;
    24.         }
    25.  
    26.         if (good) {
    27.             Img.SetActive(false);
    28.             //Img.enabled = false;
    29.         }
    30.     }
    31. }
    32.  
    33.  
     
    Last edited: Aug 27, 2015
  2. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    Try:
    Code (CSharp):
    1. public class ToggleAvailabilityScript : MonoBehaviour
    2. {
    3.      public GameObject target;   // <--- link via inspector
    4.  
    5.      public bool isTargetEnabled;
    6.      bool m_oldValue;
    7.  
    8.      void Start()
    9.      {
    10.           // ensure old value is different in order to trigger toggle at Start() if you set false in inspector
    11.           m_oldValue = !isTargetEnabled;
    12.      }
    13.  
    14.      void Update()
    15.      {
    16.           if (m_oldValue != isTargetEnabled)
    17.           {
    18.                m_oldValue = isTargetEnabled;
    19.                target.SetActive( isTargetEnabled );
    20.           }
    21.      }
    22.  
    23.      public void Toggle()
    24.      {
    25.           isTargetEnabled = !isTargetEnabled;
    26.      }
    27. }
    If you insist on using tags and GameObject.Find(), at least declare a public string:
    Code (CSharp):
    1. public class ToggleAvailabilityScript : MonoBehaviour
    2. {
    3.      public string targetTag;   // <--- link via inspector
    4.  
    5.      public bool isTargetEnabled;
    6.      bool m_oldValue;
    7.      GameObject m_target;
    8.  
    9.      void OnEnabled()
    10.      {
    11.           m_target = GameObject.Find(targetTag);
    12.           if (m_target == null )
    13.           {
    14.                Debug.LogError( "ToggleAvailabilityScript: Could not find gameObject with tag:"+targetTag );
    15.                this.enabled = false;
    16.                return;
    17.           }
    18.  
    19.           // ensure old value is different in order to trigger toggle if you set false in inspector
    20.           m_oldValue = !isTargetEnabled;
    21.      }
    22.  
    23.      void Update()
    24.      {
    25.           if (m_oldValue != isTargetEnabled)
    26.           {
    27.                m_oldValue = isTargetEnabled;
    28.                m_target.SetActive( isTargetEnabled );
    29.           }
    30.      }
    31.  
    32.      public void Toggle()
    33.      {
    34.           isTargetEnabled = !isTargetEnabled;
    35.      }
    36. }
    Hope it helps!
     
  3. MadeThisName

    MadeThisName

    Joined:
    Mar 14, 2015
    Posts:
    115
    Thankyou for the kind reply. The main problem im having is geting the target Canvas/Img via script and not using the inspectors drag and drop due to game design but I cant seem to find a solution. Once again thank you.


    Unfortunately it didn't work. I expanded upon your example but that didn't work either. Im having a funny feeling that because it has to do with the canvas i cant use the standard gameobject reference.
     
    Last edited: Aug 27, 2015
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Please elaborate on why you can't hook it up with inspector drag and drop. Is this a game object that is created dynamically?

    If there really is a good reason you can't assign it as a property (or better yet, hook up a UnityEvent), then finding it via a tag (as @Fajlworks suggests) is probably the right way to go. It will work if done correctly. Please expand on what you did, and exactly how it failed to work.
     
  5. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    Only reason I can think of as why your script does not work is that when the script runs your Canvas/Img is not present in the Scene hierarchy.

    Adjust the script a bit:
    Code (CSharp):
    1. public class ToggleAvailabilityScript : MonoBehaviour
    2. {
    3.      public string targetName;   // <--- link via inspector
    4.      public bool isTargetEnabled;
    5.      bool m_oldValue;
    6.      GameObject m_target;
    7.      Coroutine m_coroutine;
    8.  
    9.      void OnEnable()
    10.      {
    11.           m_coroutine = StartCoroutine( ScannerCoroutine() );
    12.           // ensure old value is different in order to trigger toggle if you set false in inspector
    13.           m_oldValue = !isTargetEnabled;
    14.      }
    15.  
    16.      void OnDisable()
    17.      {
    18.           if (m_coroutine != null)
    19.           {
    20.                StopCoroutine( m_coroutine );
    21.                m_coroutine = null;
    22.           }
    23.      }
    24.      void Update()
    25.      {
    26.           if ( m_target == null )
    27.                return;
    28.  
    29.           if (m_oldValue != isTargetEnabled)
    30.           {
    31.                m_oldValue = isTargetEnabled;
    32.                m_target.SetActive( isTargetEnabled );
    33.           }
    34.      }
    35.      public void Toggle()
    36.      {
    37.           isTargetEnabled = !isTargetEnabled;
    38.      }
    39.  
    40.      IEnumerator ScannerCoroutine()
    41.      {
    42.           while ( m_target == null )
    43.           {
    44.                m_target = GameObject.Find(targetName);
    45.                yield return new WaitForSeconds(1f);
    46.           }
    47.      }
    48. }
    A coroutine will search for your target object each second. If at that point doesn't work, I'm afraid but the solution is in another castle. I would advise you to reconsider your design around how you load and use your UI.

    Good luck!
     
  6. MadeThisName

    MadeThisName

    Joined:
    Mar 14, 2015
    Posts:
    115

    Your Awesome Fajlworks ! Thankyou your last reply solved my issue. I wouldn't have came to that conclusion without your help and i couldn't imagine the amount of work it would have taken for me alone to rewrite everything else to accommodate.

    Its strange since i tested everything for curiosity sake on a new scene and it still seems that the only way to toggle a child image of the canvas without the inspectors drag and drop is the method shown above. Am i missing something here? Why isnt it as easy as Get and Set. OPEN FOR DEBATE!! lol.

    Thankyou Once again.
     
  7. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    If I understand correctly, your initial version of ToggleVisible script was attached to a separate gameObject, acting as a manager sort of:

    Code (CSharp):
    1. void Start() {
    2.         Image Img = GameObject.Find ("/Canvas/Img").gameObject.GetComponent<Image> ();
    3.         //Image Img = GameObject.Find ("/Canvas/Img").GetComponent<UnityEngine.UI.Image> ();
    4.     }
    Since you mentioned that you load your UI gameObjects at a later time ( they are not present within scene when you run your app ), your script only searched once for your gameObject using Find(). Since your gameObject was not loaded at the time Start() fired, result was null.

    For future endeavours, you should do the opposite. Instead searching for your canvas object, have your newly created prefab search for the manager.
    Code (CSharp):
    1. public ToggleAvailabilityBehaviour : MonoBehaviour
    2. {
    3.      public MyManagerScript manager;
    4.      public string managerName;
    5.  
    6.      void Start()
    7.      {
    8.           GameObject obj = GameObject.Find( managerName );
    9.           if (obj == null)
    10.           {
    11.                Debug.LogError("ToggleAvailabilityBehaviour: Manager gameObject named "+managerName+" not found in scene!");
    12.                this.enabled = false;
    13.                return;
    14.           }
    15.  
    16.           manager = obj.GetComponent<MyManagerScript>();
    17.           if (manager == null)
    18.           {
    19.                Debug.LogError("ToggleAvailabilityBehaviour: Manager gameObject does not contain MyManagerScript component!");
    20.                this.enabled = false;
    21.           }
    22.  
    23.           manager.list.Add( gameObject );
    24.      }
    25.  
    26.      void OnDestroy()
    27.      {
    28.           if ( manager.list.Contains( gameObject ) )
    29.                manager.list.Remove( gameObject );
    30.      }
    31.  
    32. }
    Now your manager can toggle on/off any object you added:
    Code (CSharp):
    1. public class MyManagerScript : MonoBehaviour
    2. {
    3.      public List<GameObject> list = new List<GameObject>();
    4.  
    5.      public void ToggleAll()
    6.      {
    7.            foreach (GameObject obj in list)
    8.            {
    9.                 obj.SetActive( !obj.activeSelf );
    10.            }
    11.      }
    12.  
    13.      public void Toggle(int index)
    14.      {
    15.           if (index < 0 || index >= list.Count)
    16.                return;
    17.  
    18.           list[index].SetActive(  !list[index].activeSelf );
    19.      }
    20.  
    21.      public void Toggle( GameObject obj )
    22.      {
    23.           // if (list.Contains( obj ))    // <--- if you want to toggle only objects added
    24.                obj.SetActive( !obj.activeSelf );
    25.      }
    26. }
    Searching for manager should be more logical and less error prone because manager "should by design" be always present from the start. But then again it all depends how you structure your app, as there are multiple ways to solve problems.

    Hope this helps a bit. Good luck!
     
    Last edited: Aug 27, 2015
    MadeThisName and JoeStrout like this.
  8. MadeThisName

    MadeThisName

    Joined:
    Mar 14, 2015
    Posts:
    115
    "Helps a bit"......Don't be so modest your help has been invaluable. Your Logic is sound and I cant thank you enough for your time. I mainly do sound and graphics so your coding knowledge has helped me greatly and i am positive others to come. Before i posted this question i scoured the web for 4 hours and came up with little to no information in regards to the UI canvas and calling it via another script. Now that shouldn't happen thanks to your input.

    Thankyou kindly.

     
    Last edited: Aug 28, 2015