Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Sanity Check] WorldToScreenPoint and OnGUI Manager?

Discussion in 'Immediate Mode GUI (IMGUI)' started by GregMeach, Jul 9, 2014.

  1. GregMeach

    GregMeach

    Joined:
    Dec 5, 2012
    Posts:
    249
    Scene: 3D space (no gravity)
    Space objects (e.g. station, asteroids, other ships, etc) run this code in OnGUI():
    Code (CSharp):
    1.  
    2.         // In OnGUI()
    3.         Vector3 sp = Camera.main.WorldToScreenPoint(_cachedTransform.position);
    4.         sp.y = Screen.height - sp.y;
    5.  
    6.        [B] if (sp.z >= 0) {[/B]
    7.               // Display gui stuff
    8.         }
    9.  
    In reading the docs the Vector3.z should be able to tell me if the camera is in FRONT or BEHIND the object. Until I added the "sp.z >= 0" I was seeing odd opposite OnGUI stuff even when my ship was past the objects. A quick test and now once the camera has moved past the object, I no longer see the odd gui texture.

    On a related topic: If my scene will have like 40-200 objects all running this OnGUI() code; should I instead create a GUIManager that will track my space objects and then display them in one OnGUI() call?

    Thanks

    Ref this post: http://forum.unity3d.com/threads/nametags-over-players-is-extremely-slow.132586/#post-1049183
     
  2. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    I also use a similar setup to determine if an object is visible.
    Code (csharp):
    1.  
    2.   private Vector3 _screenPos;
    3.    private bool _onScreen;
    4.  
    5.    private void Update ()
    6.    {
    7.      _screenPos = Camera.main.WorldToScreenPoint( transform.position );
    8.      _onScreen = Camera.main.pixelRect.Contains( _screenPos ) && _screenPos.z > Camera.main.nearClipPlane;
    9.    }
    10.  
    11.    private void OnGUI()
    12.    {
    13.      if(_onScreen)
    14.      {
    15.              // your display stuff here
    16.      }
    17.    }
    18.  
    Note that OnGUI is called several times per frame and thus you execute the test unneccessarily. Thus I do it once in upate and act accordingly in OnGUI.
    The z-test is mandatory to avoid "ghost" displays from behind the camera. In my opinion the rect.contains method should test this automatically.
    The game Starpoint Gemini has the same problem.

    Also note that the screenrect should be a bit larger to avoid stuff "popping in" if you desire a smooth effect.

    Regarding to your manager question. I would say it does not really matter since all objects need to be tested and all visible displayed so the only overhead you could save is the call of 400 empty update or ongui calls. To be sure you would need to profile yourself though but if you don't need the manager for other reasons (interaction, managing) I would avoid it.




    EDIT:
    you do not check if an object is on the screen at all and this may eat up performance heavily since each gui element adds its own draw call. so if you follow my method your game should run noticeably faster especially with this much objects. If you try it out i would apreciate some "benchmark" numbers.
     
    Last edited: Jul 13, 2014
  3. GregMeach

    GregMeach

    Joined:
    Dec 5, 2012
    Posts:
    249
    AWESOME! - thank you :)

    Those last two paragraphs are a big help in my design and of course it (now) makes perfect sense to only display info on visible (or in camera) objects. It did not occur to me to use Update() along with OnGUI() (DOH!)

    I am going to utilize some sort of "manager"; to allow all my space scene objects a place to register and track the "lists" I'll need.

    It makes sense (to me) that it would be much less costly (both GPU and CPU) to have the manager hold a single copy of say my asteroid target reticle and then display multiple copies of it on any visible asteroids.

    I'll have to check and see if this also reduces the draw calls (instead of each asteroid calling OnGUI).
    Thank-you again