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

Using Unity for a GUI only application

Discussion in 'Scripting' started by Elecman, Sep 13, 2013.

  1. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    I am writing an application which only displays text and the occasional jpg. Using Unity for a GUI only application might seem a bit overkill but the ease to publish to different platforms outweighs the overhead issues.

    There is only one problem though. Since the screen content is 100% static most of the time (apart from swipe animations), I do not want to waste CPU/GPU cycles by rendering static stuff, which eats up the battery. So I only want to render the camera when I tell it to.

    So isn't there another way to render the screen only once and then somehow freeze the frame buffer? If I just disable the camera game object or camera component, the screen turns black. If I disable the camera and then call .Render() on it, it doesn't do anything, presumably because .Render() only renders into a render texture and not into the frame buffer. I tried playing with the camera clear flags, but that didn't work as well. I suppose I could render the frame to a render texture, point the camera to that render texture, and disable all content. But that requires Pro and I want to avoid using that.

    Any ideas?
     
  2. Xare

    Xare

    Joined:
    Jun 28, 2013
    Posts:
    1
    You could try setting the culling mask to "nothing" and clear flags to "depth only".
     
  3. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Just tried it but if I do that the camera doesn't render anything.
     
  4. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    After you rendered your Image:

    1. Try to disable the main camera
    2. When 1. doesnt work try to enable a camera which has Nothing as culling mask and DepthOnly as clearflag. Also disable the MainCamera.

    If even this fails, try to take a screenshot of the rendered image (Texture2D offers a method for this) and display this screenshot only.

    Also you can try to use the Unity feature which stops rendering anything when the window has no focus, by removing the focus, but this requires some PInvoke magic and Windows.
     
  5. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks, I got it to work now (on windows).

    EDIT:
    I just found out that it doesn't work on Android (tested on HTC One) but it works fine on Windows. This is very unfortunate because the battery on my laptop is a lot larger then the one in my phone. Bug report filed.

    Here are some pointers:

    -You cannot disable the camera. If you do so, will clear the frame buffer and nothing will be shown.
    -Camera.Render() after disabling a camera will not work as it will only render to a RenderTexture and not to the frame buffer. It does work if used together with setting the camera clear flags and culling mask as shown below.
    -Rendering (or suspending rendering) is controlled by setting the culling mask to "everything" (render) and "nothing" (stop rendering).
    -To prevent the camera from overwriting the frame buffer, set the clear flags to "depth only" or "don't clear".
    -GuiText needs a geometry (plane) background, if the clear flags and culling mask are set in the Editor, otherwise the text is not anti-aliased. This bug doesn't seem to be an issue when the clear flags and culling mask are set via a script.
    -Do not use build in GUI elements such as buttons (text is ok) as these are drawn even though the camera is set to "StopRender" as described below. Hopefully the new Unity GUI system in the works will be better in this regard.

    The code below allows you to "freeze camera", "stop rendering", or "render only once", useful to save the battery in static scenes.

    Code (csharp):
    1.  
    2. private CameraClearFlags storedClearFlags;
    3. private int storedCullingMask;
    4.  
    5. void Start () {
    6.  
    7.     //save clear flags
    8.     storedClearFlags = Camera.main.clearFlags;
    9.  
    10.     //save the culling mask
    11.     storedCullingMask = Camera.main.cullingMask;
    12. }
    13.    
    14. void Update () {
    15.    
    16.     if(Input.GetKeyDown(KeyCode.LeftArrow)){
    17.  
    18.         StartRender();
    19.     }
    20.  
    21.     if(Input.GetKeyDown(KeyCode.DownArrow)){
    22.  
    23.         StopRender();
    24.     }
    25.  
    26.     if(Input.GetKeyDown(KeyCode.RightArrow)){
    27.  
    28.         RenderOnce();
    29.     }
    30. }
    31.  
    32. void StartRender(){
    33.  
    34.     //first change the clear flags to nothing
    35.     Camera.main.clearFlags = storedClearFlags;
    36.  
    37.     //now change the culling mask to nothing
    38.     Camera.main.cullingMask = storedCullingMask;
    39. }
    40.  
    41. void StopRender(){
    42.  
    43.     //first change the clear flags to nothing
    44.     Camera.main.clearFlags = CameraClearFlags.Nothing;
    45.  
    46.     //now change the culling mask to nothing
    47.     Camera.main.cullingMask = 0;
    48. }
    49.  
    50. void RenderOnce(){
    51.  
    52.     StartRender();
    53.     Camera.main.Render();
    54.     StopRender();
    55. }
    56.  
    This method works (not on mobile) but it is a bit clunky. I think Unity should allow for a more elegant way of using GUI-only apps.

    Similar issues:
    http://answers.unity3d.com/questions/147988/how-to-pause-the-main-camera-.html
    http://forum.unity3d.com/threads/107939-Frame-rate-control-on-Android-extending-battery-life
    http://forum.unity3d.com/threads/141519-How-to-save-battery
    http://answers.unity3d.com/questions/245873/reduce-battery-consumption-as-much-as-possible.html
    http://forum.unity3d.com/threads/187935-Unity3D-CPU-Usage
    http://answers.unity3d.com/questions/129268/android-quotclear-flags-of-cameraquot.html?sort=oldest
    http://answers.unity3d.com/questions/319430/camera-dont-clear-flag-doesnt-work-on-android-.html

    Please support the lobby for this on Unity feedback here:
    http://feedback.unity3d.com/suggest...er-loop-for-lower-power-consumption-on-mobile
     
    Last edited: Apr 29, 2015
    PizzaProgram likes this.
  6. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    I tried a few more things:

    -Screen capture using ReadPixels() This takes about 3 seconds on an HTC One and freezes everything in the process.
    -RenderTexture is fast but I only have a desktop Pro version.
    -Application.targetFrameRate set to 1: still rendering albeit slow. User input is super laggy though, even if the routines are placed in FixedUpdate with the frame rate set to normal if user input is detected. Still too slow.
    -System.Threading.Thread.Sleep() is asking for trouble.

    So after using Unity for 2 years, I have finally run into a limitation. Unity is a battery hog. You cannot even simply stop rendering.
     
    Last edited: Sep 16, 2013
  7. gilianp

    gilianp

    Joined:
    Mar 24, 2014
    Posts:
    4
    Hi! I'm glad to say that now in unity 5 is working for iOS!
    Just use the method proposed by Elecman, thanks guy!
     
  8. gilianp

    gilianp

    Joined:
    Mar 24, 2014
    Posts:
    4
    I've tested and work very nice. On xcode debug my app in idle state (running 60 fps UI only) consumes 37% of CPU, in the moment that render is stoped the consume drop down to 16%, but the best is that the Input is continued working at 60 fps, perfect. Another cool fact is that not have any heavy processing to Start/Stop render, the swap is immediatly!
     
  9. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Sorry, there have been several different approaches mentioned on this thread, and I'm a bit confused.

    Can you summarize what you're doing that drops the CPU usage down so nicely?
     
  10. blazespinnaker

    blazespinnaker

    Joined:
    Dec 20, 2015
    Posts:
    80
    Looks great, will try. Any updated pointers on this subject would be appreciated.
     
  11. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Since this thread was written there have been other cross platform frameworks released. Current advice is to try something like Xarmin.
     
  12. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Perhaps with the upcoming custom render loop it will be possible to pause the render loop and thus save battery. But I agree that the best solution is a dedicated native 2d solution like Xamarin. Especially since it is free now.
     
  13. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Unless you want to support the Mac. Xamarin's support for the Mac was very weak before (trust me, I really tried it), and now that it's been bought out by Microsoft, I consider it walking dead now. For cross-platform desktop games, Unity is still by far the best tool. For cross-platform desktop apps, you'd be better off using Xojo (which has done a lot of dumb things in the last five years, but is still the best tool in that space).
     
  14. blazespinnaker

    blazespinnaker

    Joined:
    Dec 20, 2015
    Posts:
    80
    Xamarin is a nightmare. Extremely familiar with it. Write once, debug everywhere. Hardly cross platform at all. Besides, I need desktop support.

    The only proper way to do this is OpenGL cross platform kit. Admittedly, my particular app (graphical dashboard) works well for this particular use case, but I think it would be extended to a lot of others non game apps.