Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Text Gizmo

Discussion in 'Scripting' started by cecarlsen, Aug 5, 2009.

  1. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    Is there any way of drawing text in the scene view other than rendering text dynamically into textures and using Gizmos.DrawIcon()?

    I really miss this feature for debugging purposes.

    ~ce
     
    Fangh likes this.
  2. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    I successfully created a singleton script that can render text gizmos in the scene view. It's not pretty. I use readymade character textures and call Gizmos.DrawIcon() for each character.

    Now, I can't get the transparency working. Can anyone please help me with this?

    The script and textures can be downloaded here:
    http://sixthsensor.dk/temp/unityforum/TextGizmo.zip

    Place the TextGizmo folder in "Assets/Gizmos/". Then call TextGizmo.Draw( Vector3 position, string text ) from OnGizmos() in any MonoBehaviour.

    Code (csharp):
    1.  
    2. /*
    3. *   TextGizmo.cs
    4. *   August 2009
    5. *   Carl Emil Carlsen
    6. *   sixthsensor.dk
    7. */
    8.  
    9. using UnityEngine;
    10. using System.Collections.Generic;
    11.  
    12.  
    13. public class TextGizmo
    14. {
    15.     private static TextGizmo tg = null;
    16.     private Dictionary<char,string> texturePathLookup;
    17.     private Camera editorCamera = null;
    18.     private const int CHAR_TEXTURE_HEIGHT = 8; // todo: line breaks
    19.     private const int CHAR_TEXTURE_WIDTH = 6;
    20.     private const string characters = "abcdefghijklmnopqrstuvwxyz0123456789";
    21.    
    22.    
    23.     public static void Init()
    24.     {
    25.         tg = new TextGizmo();
    26.     }
    27.    
    28.    
    29.     /* singleton constructor */
    30.     private TextGizmo()
    31.     {
    32.         editorCamera = Camera.current;
    33.         texturePathLookup = new Dictionary<char,string>();
    34.         for( int c=0; c<characters.Length; c++ ){
    35.             texturePathLookup.Add( characters[c], "TextGizmo/text_" + characters[c] + ".tif" );
    36.         }
    37.     }
    38.    
    39.    
    40.     /* only call this method from a OnGizmos() method */
    41.     public static void Draw( Vector3 position, string text )
    42.     {
    43.         if( tg == null ) Init();
    44.        
    45.         string lowerText = text.ToLower();
    46.         Vector3 screenPoint = tg.editorCamera.WorldToScreenPoint( position );
    47.         int offset = 20;
    48.         for( int c=0; c<lowerText.Length; c++ )
    49.         {  
    50.             if( tg.texturePathLookup.ContainsKey( lowerText[c] ) )
    51.             {
    52.                 Vector3 worldPoint = tg.editorCamera.ScreenToWorldPoint( new Vector3( screenPoint.x + offset, screenPoint.y, screenPoint.z ) );
    53.                
    54.                 Gizmos.DrawIcon( worldPoint, tg.texturePathLookup[ lowerText[c] ] );
    55.                
    56.                 offset += CHAR_TEXTURE_WIDTH;
    57.             }
    58.         }
    59.     }
    60. }
     

    Attached Files:

    Cloud-Yo and forestrf like this.
  3. FiveFingers

    FiveFingers

    Joined:
    Oct 15, 2009
    Posts:
    541
    What's the format of the image I should use for the gizmos icons ?

    I tried a generic 256 x 128 tga with alpha and dint worked.

    Only TIFF ?

    Any other restrictions ?
     
  4. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    I haven't checked, but I assume the image format restrictions (if any) are described in the documentation for Gizmos.DrawIcon() which is the method I use to display the letters. I generated the letters using Processing, but I suppose you could do that in Unity as well.

    ~ce


    This is all you need to generate the letters.

    Code (csharp):
    1.  
    2. PFont font;
    3. String alphabet = "abcdefghijklmnopqrstuvwxyzæøå0123456789.,;:+-(){}/!#%= ";
    4.  
    5.  
    6. void setup()
    7. {
    8.  size( 6, 10 );
    9.  noLoop();
    10.  
    11.  
    12.  font = createFont( "DroidSansMono", 10 );
    13.  textFont( font, 10 );
    14.  
    15.   stroke( 255 );
    16.   noFill();
    17.  
    18.   for( int s=0; s<alphabet.length(); s++)
    19.   {
    20.     background( 0 );
    21.     text( alphabet.charAt(s), 0, 8 );
    22.     saveFrame( "alphabet/text_" + alphabet.charAt(s) + ".tif" );
    23.   }
    24. }
     
    Cloud-Yo likes this.
  5. Wox

    Wox

    Joined:
    Dec 14, 2009
    Posts:
    93
    Gizmos icon i think must be in a Gizmo(s) folder if i remeber right.
     
  6. Zombie Gecko

    Zombie Gecko

    Joined:
    Nov 25, 2010
    Posts:
    32
    This is a bit old, but just wanted to say thanks for this script! Helped me out loads...:)
     
  7. VivienS

    VivienS

    Joined:
    Mar 25, 2010
    Posts:
    24
  8. qaat

    qaat

    Joined:
    Jun 27, 2011
    Posts:
    1
    Your package didn't include the updated script. It would be great to get that line break support instead of me coding it again. :)
     
  9. scadieux

    scadieux

    Joined:
    Sep 14, 2011
    Posts:
    20
    Just in case someone else need that new-line feature, I hacked something quick:
    Code (csharp):
    1.  
    2. #if UNITY_EDITOR
    3. using UnityEngine;
    4. using System.Collections.Generic;
    5.  
    6. public class TextGizmo
    7. {
    8.     #region Singleton
    9.     private class Singleton
    10.     {
    11.         static Singleton()
    12.         {
    13.             if (instance == null)
    14.             {
    15.                 instance = new TextGizmo();
    16.             }
    17.         }
    18.        
    19.         internal static readonly TextGizmo instance;
    20.     }
    21.    
    22.     public static TextGizmo Instance { get { return Singleton.instance; } }
    23.    
    24.     #endregion
    25.    
    26.     private const int CHAR_TEXTURE_HEIGHT = 11;
    27.     private const int CHAR_TEXTURE_WIDTH = 8;
    28.     private const string characters = " !#%'()+,-.0123456789;=abcdefghijklmnopqrstuvwxyz_{}~\\?\":/*";
    29.  
    30.     private Dictionary<char,string> texturePathLookup;
    31.     private Dictionary<char, string> specialChars;
    32.  
    33.     private TextGizmo()
    34.     {
    35.         specialChars = new Dictionary<char, string>();
    36.         specialChars.Add('\\', "backslash");
    37.         specialChars.Add('?', "questionmark");
    38.         specialChars.Add('"', "quotes");
    39.         specialChars.Add(':', "colon");
    40.         specialChars.Add('/', "slash");
    41.         specialChars.Add('*', "star");
    42.        
    43.         texturePathLookup = new Dictionary<char,string>();
    44.         for( int c=0; c<characters.Length; c++ )
    45.         {
    46.             string charName = specialChars.ContainsKey(characters[c]) ? specialChars[characters[c]] : characters[c].ToString();
    47.             texturePathLookup.Add(characters[c], "TextGizmo/text_" + charName + ".png");
    48.         }
    49.     }
    50.    
    51.     public void DrawText(Camera camera, Vector3 position, object message) { DrawText(camera, position, message != null ? message.ToString() : "(null)"); }
    52.     public void DrawText(Camera camera, Vector3 position, string format, params object[] args) { DrawText(camera, position, string.Format(format, args)); }
    53.  
    54.     private void DrawText(Camera camera, Vector3 position, string text)
    55.     {  
    56.         string lowerText = text.ToLower();
    57.         Vector3 screenPoint = camera.WorldToScreenPoint(position);
    58.        
    59.         Vector3 offset = Vector3.zero;
    60.         for(int c = 0, n = lowerText.Length; c < n; ++c)
    61.         {  
    62.             if ('\n'.Equals(lowerText[c]))
    63.             {
    64.                 offset.y += CHAR_TEXTURE_HEIGHT + 2;
    65.                 offset.x = 0;
    66.                 continue;
    67.             }
    68.             else if(texturePathLookup.ContainsKey(lowerText[c]))
    69.             {
    70.                 Gizmos.DrawIcon(camera.ScreenToWorldPoint(screenPoint + offset), texturePathLookup[lowerText[c]]);
    71.                 offset.x += CHAR_TEXTURE_WIDTH;
    72.             }
    73.         }
    74.     }
    75. }
    76. #endif
    77.  
    In order to use that script you'll need the unity package posted previously.
     
    Cloud-Yo likes this.
  10. mboog12

    mboog12

    Joined:
    Oct 4, 2011
    Posts:
    86
    thumbs up! really helpful
     
  11. Catman

    Catman

    Joined:
    Jul 16, 2011
    Posts:
    45
    Really helpful, thanks for the feature!
     
  12. devin5

    devin5

    Joined:
    Dec 24, 2011
    Posts:
    5
    Why would you need this when you can simply call GUI.TextField inside OnDrawGizmos() ?
     
  13. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    742
    just tried it... that doesn't seem to draw anything
     
  14. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    339
    Hi,

    The package + the last source code posted doesn't draw anything for me :( Could someone send a full package with a working sample scene please ?
     
  15. jquave

    jquave

    Joined:
    Oct 3, 2009
    Posts:
    21
    Little late, but I figured I would post it here for people still looking at this thread:

    https://www.dropbox.com/s/60ffjzx27agrgr0/TextGizmo.unitypackage
     
  16. ProgrammerJens

    ProgrammerJens

    Joined:
    Jun 3, 2013
    Posts:
    12
  17. fairchild670

    fairchild670

    Joined:
    Dec 3, 2012
    Posts:
    69
    Was looking for something similar to the above and found the Handles class http://docs.unity3d.com/Documentation/ScriptReference/Handles.html works nicely:

    Code (csharp):
    1. function OnDrawGizmos() {
    2.     Handles.Label(transform.position, transform.name);
    3. }
    4.  
    Easy to only label objects of a certain type.
     
  18. s_guy

    s_guy

    Joined:
    Feb 27, 2013
    Posts:
    102
  19. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    576
  20. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,195
    hey, this works! Thanks! Just make sure to wrap on #if UNITY_EDITOR.
     
    Marc-Saubion and Develax like this.
  21. Thormor

    Thormor

    Joined:
    Nov 22, 2012
    Posts:
    39
  22. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    399
    This one works nicely as well:
    Code (CSharp):
    1.  
    2. public class Debug2Mono : MonoBehaviour
    3. {
    4.     public class Debug2String
    5.     {
    6.         public Vector3 pos;
    7.         public string text;
    8.         public Color? color;
    9.     }
    10.  
    11.     public List<Debug2String> Strings = new List<Debug2String>();
    12.  
    13.     public void OnDrawGizmos()
    14.     {
    15.         foreach ( var stringpair in Strings )
    16.         {
    17.             UnityEditor.Handles.color = stringpair.color.HasValue ? stringpair.color.Value : Color.green;
    18.             UnityEditor.Handles.Label (stringpair.pos, stringpair.text);
    19.         }
    20.     }
    21. }
    call it via:
    Code (CSharp):
    1. // ... your class here
    2.  
    3.  
    4.     private static Debug2Mono m_instance;
    5.     public static Debug2Mono instance {
    6.         get
    7.         {
    8.             if ( m_instance == null )
    9.             {
    10.                 m_instance = GameObject.FindObjectOfType<Debug2Mono>();
    11.                 if ( m_instance == null )
    12.                 {
    13.                     var go = new GameObject("DeleteMeLater");
    14.                     m_instance = go.AddComponent<Debug2Mono>();
    15.                 }
    16.             }
    17.             return m_instance;
    18.         }
    19.     }
    20.  
    21.     public static void DrawText(Vector3 pos, string text, Color? color = null)
    22.     {
    23.         instance.Strings.Add ( new Debug2Mono.Debug2String() { text = text, color = color, pos = pos} );
    24.     }
     
    Cloud-Yo and Headworker like this.
  23. Headworker

    Headworker

    Joined:
    Sep 6, 2012
    Posts:
    28
    Thank you Xelnath, it does work really well.

    Another way to use it would be to have a the script itself attached to a single GameObject.

    Just make the Strings list static and you can use a static method form everywhere to add debugObjects to it.

    Anyway, thanks a lot, this is really helpful!
     
  24. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    576
    Except it wont work in build, and require unity editor assembly.
     
  25. Headworker

    Headworker

    Joined:
    Sep 6, 2012
    Posts:
    28
    Thats right, pointcache. You will get builderrors if you leave this in place when building your project. But for editor debugging it worked well enough. Or do know an option that does work with builds?
     
  26. Willkuerlich

    Willkuerlich

    Joined:
    Sep 23, 2014
    Posts:
    13
    You could do some additional checking:

    public static class UHelper {

    public static bool IsEditorEnviromentPlaymode = Application.isEditor && !Application.isPlaying ? true : false;
    public static bool IsGameEnviromentPlaymode = !Application.isEditor && Application.isPlaying ? true : false;
    }
     
  27. tarahugger

    tarahugger

    Joined:
    Jul 18, 2014
    Posts:
    129
    For google time-travellers: version with background behind text

    Code (CSharp):
    1.     public static void DrawString(string text, Vector3 worldPos, Color? textColor = null, Color? backColor = null)
    2.     {
    3.         UnityEditor.Handles.BeginGUI();
    4.         var restoreTextColor = GUI.color;
    5.         var restoreBackColor = GUI.backgroundColor;
    6.  
    7.         GUI.color = textColor ?? Color.white;
    8.         GUI.backgroundColor = backColor ?? Color.black;
    9.  
    10.         var view = UnityEditor.SceneView.currentDrawingSceneView;
    11.         if (view != null && view.camera != null)
    12.         {
    13.             Vector3 screenPos = view.camera.WorldToScreenPoint(worldPos);
    14.             if (screenPos.y < 0 || screenPos.y > Screen.height || screenPos.x < 0 || screenPos.x > Screen.width || screenPos.z < 0)
    15.             {
    16.                 GUI.color = restoreTextColor;
    17.                 UnityEditor.Handles.EndGUI();
    18.                 return;
    19.             }
    20.             Vector2 size = GUI.skin.label.CalcSize(new GUIContent(text));            
    21.             var r = new Rect(screenPos.x - (size.x / 2), -screenPos.y + view.position.height + 4, size.x, size.y);
    22.             GUI.Box(r, text, EditorStyles.numberField);
    23.             GUI.Label(r, text);
    24.             GUI.color = restoreTextColor;
    25.             GUI.backgroundColor = restoreBackColor;
    26.         }
    27.         UnityEditor.Handles.EndGUI();
    28.     }
     
    Kevin-VFX, Karabin, Cloud-Yo and 9 others like this.
  28. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,720
    Ultimate sweet stuff :eek:
     
    iRYO400, giraffe1 and kangsangyeon like this.
  29. Cloud-Yo

    Cloud-Yo

    Joined:
    Sep 5, 2014
    Posts:
    12
    Why is Unity not funding this?!?! thanks guys, extremely useful!
     
  30. krisam

    krisam

    Joined:
    Jan 14, 2022
    Posts:
    1
    I believe tecnically you can create TextMeshes and use Gizmos.DrawMesh or Gizmos.DrawWiredMesh...

    haven't tried it though. I have it on my dev list
     
  31. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,720
    More time traveling after over 3 years...

    Didn't Unity update the DrawGizmo class yet?....
     
    tuccci likes this.