Search Unity

  1. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  2. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  3. If you couldn't join the live stream, take a peek at what you missed.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  5. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  6. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Draw a simple rectangle filled with a color

Discussion in 'Extensions & OnGUI' started by Cascho01, Dec 21, 2011.

  1. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    979
    We can draw labels with a texture inside, but how to draw a rectangle (label) with just a color in it?
     
  2. jedy

    jedy

    Joined:
    Aug 1, 2010
    Posts:
    574
    1. Create a new Texture2D(1,1)
    2. Fill it with the desired color ( SetPixel )
    3. Set it's wrap mode to repeat
    4. Use Texture2D.Apply() to apply the changes
    5. Create a GUIStyle
    6. Set it's .normal background texture to the texture you just created
     
  3. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    979
    Thanks, that´s what I do so far, thought there must be an easier way!
     
  4. jedy

    jedy

    Joined:
    Aug 1, 2010
    Posts:
    574
    This is pretty efficient. No need for anything else.
     
  5. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    979
    function OnGUI () {
    GUI.Label (Rect (25, 25, 100, 30), color);
    }

    would be muuuuuch easier :D
     
  6. jedy

    jedy

    Joined:
    Aug 1, 2010
    Posts:
    574
    It's how it should look
    GUI.Label(Rect(25, 25, 100, 30), style);
    Simple as that.

    Make sure to initialize the texture2d and the style just once, otherwise your garbage collection will go crazy and cause spikes.
     
  7. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    979
    Ok, thanks, what I don´t like is filling up a texture and blowing it up just to render some pixels on screen -especially when the color is changing often in runtime.
    No problem if there´s no other way!
     
  8. kblood

    kblood

    Joined:
    Jun 20, 2012
    Posts:
    56
    I found this code in another thread and it helped me doing this easy:

    void DrawQuad(Rect position, Color color) {
    Texture2D texture = new Texture2D(1, 1);
    texture.SetPixel(0,0,color);
    texture.Apply();
    GUI.skin.box.normal.background = texture;
    GUI.Box(position, GUIContent.none);
    }

    I hope it helps others as well.
     
    ARRAYEWHY, deadlyfingers and Ash-Blue like this.
  9. ProbePLayer

    ProbePLayer

    Joined:
    Oct 19, 2012
    Posts:
    10
    Awesome! that code really worked for me. Thanks kblood.
     
  10. IQpierce

    IQpierce

    Joined:
    Jan 24, 2011
    Posts:
    35
    kblood's code is horrible and will cause your game to break. Do not use it. Read the warning from jedy two messages up: initializing a new Texture2D object in every OnGUI call (i.e. every frame) will be a huge memory problem. Additionally, there's no reason to set "GUI.skin.box.normal.background" - this is changing the look of a default skin and can affect how other GUIs appear.

    As an aside, I don't understand why this is so hard to do in Unity's own GUI tools - why aren't there simple DrawRect, DrawLine, DrawCircle, etc. functions? It's very odd to me.

    Here is code that works and doesn't chew through memory indefinitely:

    Code (csharp):
    1.  
    2.    
    3.     private static Texture2D _staticRectTexture;
    4.     private static GUIStyle _staticRectStyle;
    5.  
    6.     // Note that this function is only meant to be called from OnGUI() functions.
    7.     public static void GUIDrawRect( Rect position, Color color )
    8.     {
    9.         if( _staticRectTexture == null )
    10.         {
    11.             _staticRectTexture = new Texture2D( 1, 1 );
    12.         }
    13.  
    14.         if( _staticRectStyle == null )
    15.         {
    16.             _staticRectStyle = new GUIStyle();
    17.         }
    18.  
    19.         _staticRectTexture.SetPixel( 0, 0, color );
    20.         _staticRectTexture.Apply();
    21.  
    22.         _staticRectStyle.normal.background = _staticRectTexture;
    23.  
    24.         GUI.Box( position, GUIContent.none, _staticRectStyle );
    25.  
    26.  
    27.     }
    28.  
     
    Wright, mmilan and bluescr like this.
  11. CB-InDev

    CB-InDev

    Joined:
    Apr 4, 2014
    Posts:
    11
    Thanks for sharing, I'm new to Unity and was looking for some tutorials on simple 2D app creation.

    I find it interesting that unlike other IDEs, adding a button/box/text/etc... seems a little more complex in Unity. Maybe I am missing a toolbar or something.

    Let me know if you can help.

    As an example, in my signature I show an app (PopQuiz!) I created with Visual Studio for WIndows 8. Creating an app like this for Unity is my goal, so I can transfer it to other platforms easily.
     
  12. artificialfool

    artificialfool

    Joined:
    Nov 29, 2012
    Posts:
    2
    Thanks very much IQpierce, just what I needed.
     
  13. Rachan

    Rachan

    Joined:
    Dec 3, 2012
    Posts:
    61
    Be careful Texture2D texture = new Texture2D(1, 1); will eating your memory :)
     
  14. mh114

    mh114

    Joined:
    Nov 17, 2013
    Posts:
    270
    No need to update the texture all the time. Just set the texture pixel to white (once, when creating it) and set the GUI.color before drawing the box. (You should also save the original GUI color and restore it after drawing the box.)
     
  15. Obsidanse

    Obsidanse

    Joined:
    Mar 2, 2014
    Posts:
    3
    Why there isn't an option of (new Rect (x,y,w,h),colour) is beyond me.
     
  16. Cameron860

    Cameron860

    Joined:
    Jun 1, 2009
    Posts:
    764
    The code given in this thread isn't terribly efficent. This is what I use:

    Code (CSharp):
    1.  
    2. public static class EditorGUITools
    3. {
    4.  
    5.     private static readonly Texture2D backgroundTexture = Texture2D.whiteTexture;
    6.     private static readonly GUIStyle textureStyle = new GUIStyle {normal = new GUIStyleState { background = backgroundTexture } };
    7.  
    8.     public static void DrawRect(Rect position, Color color, GUIContent content = null)
    9.     {
    10.         GUI.backgroundColor = color;
    11.         GUI.Box(position, content ?? GUIContent.none, textureStyle);
    12.     }
    13.  
    14.     public static void LayoutBox(Color color, GUIContent content = null)
    15.     {
    16.         GUI.backgroundColor = color;
    17.         GUILayout.Box(content ?? GUIContent.none, textureStyle);
    18.     }
    19. }
    20.  
     
    Last edited: Aug 14, 2016
  17. KeinZantezuken

    KeinZantezuken

    Joined:
    Mar 28, 2017
    Posts:
    40
    Cameron860

    is
    Code (CSharp):
    1.  private static readonly Texture2D backgroundTexture = Texture2D.whiteTexture;
    possible at runtime? I tried it but the "texture" is being transparent/invisible as if it does not present. Variant with initializing new texture at Start/Awake works fine ofc:

    Code (CSharp):
    1. public void Awake()
    2. {
    3.         if(drawTexture == null )
    4.         {
    5.             drawTexture  = new Texture2D( 1, 1 );
    6.            drawTexture.SetPixel( 0, 0, color );
    7.            drawTexture.Apply();
    8.         }
    9. }
    10.  
     
  18. ARRAYEWHY

    ARRAYEWHY

    Joined:
    Jan 9, 2014
    Posts:
    4
    Works like a charm! Thank you so much!
     
  19. atorisa

    atorisa

    Joined:
    Dec 1, 2013
    Posts:
    56
  20. unity_dA5TCa2krrACsQ

    unity_dA5TCa2krrACsQ

    Joined:
    Dec 15, 2017
    Posts:
    1
    First off that was just rude. With that aside, it would be better to define the texture at the beginning in an awake or start function. Here's how I would do it:
    Code (csharp):
    1.  
    2.     private static Texture2D _staticRectTexture;
    3.     private static GUIStyle _staticRectStyle;
    4.    
    5.     void Awake(){
    6.            _staticRectTexture = new Texture2D( 1, 1 );
    7.            _staticRectStyle = new GUIStyle();
    8.     }
    9.  
    10.     public static void GUIDrawRect( Rect position, Color color )
    11.     {
    12.  
    13.         _staticRectTexture.SetPixel( 0, 0, color );
    14.         _staticRectTexture.Apply();
    15.  
    16.         _staticRectStyle.normal.background = _staticRectTexture;
    17.  
    18.         GUI.Box( position, GUIContent.none, _staticRectStyle );
    19.  
    20.     }
    21.  
     
    TashaSkyUpchurch likes this.
  21. Mikilo

    Mikilo

    Joined:
    Jan 29, 2013
    Posts:
    282
    I don't understand why he is being rude. He is clearly right. The code was horrible and people liked it.

    And your code implies to work in a MonoBehaviour, clearly not much better.
     
    Wright likes this.
  22. TashaSkyUpchurch

    TashaSkyUpchurch

    Joined:
    Jan 25, 2018
    Posts:
    8
    I agree with unity_dA5TCa2krrACsQ, IQpierce was being rude. Though likely not purposefully, some people sometimes forget to no be rude, or don't care or can't manage it because of language barriers.

    Regardless. Serious question here. What is wrong with using unity_dA5TCa2krrACsQ code in a MonoBehaviour? Isn't it standard to do nearly everything inside them? I mean. even if your class is not derived from MonoBehaviour it's likely that the thread was dispatched from one.

    Does this work with 3D games?
     
  23. NoBrainer-David

    NoBrainer-David

    Joined:
    Jan 5, 2014
    Posts:
    33
    The code relies on Awake() being called to initialize the texture and the GUIStyle. This can be achieved by putting it inside of a MonoBehavior. This, however, requires the MonoBehavior to be active somewhere in the scene.

    It would be more elegant to just construct the GUIStyle and the Texture2D statically, as Cameron860 does in his code. Then, you don't have to worry about dragging the MonoBehavior into every scene where you want this functionality.

    Putting everything inside of MonoBehaviors is the way I started out using Unity. With time, you will certainly see more and more situations where this limits you or where it makes reasoning about what is happening harder. Richard Fine held an amazing talk at Unite 2016 that totally opened my eyes to ScriptableObjects. After you are convinced and want to know more specific examples on how to let this drive the architecture of your game, Ryan Hipples talk is fantastic.
    If you are overwhelmed and don't quite see how you can turn these condensed conference-code examples into functionality for your project, check out this open-source project for implementations aimed at production use.

    Disclaimer: I started and am responsible for that project and it is still very much a work in progress.
     
    TashaSkyUpchurch likes this.
  24. Don-Tako

    Don-Tako

    Joined:
    Jan 31, 2013
    Posts:
    3
    Simple:
    Code (CSharp):
    1. public GUIStyle guiStyle;
    2.     void OnGUI()
    3.     {
    4.             GUI.Label(new Rect(0, 0, Screen.width, Screen.height), "", guiStyle);
    5.     }
    Remember set a background image on Gui Style > Normal > Background