GM2 - Animated GUIs with few drawcalls!

After 24 pages of posts in the original GUIManager thread, I figure it was time to start anew so people won’t have to read through it all to figure out how to get things moving. I’m amazed at how many people have tried the manager and I hope that it has been helpful. Thanks to all for the constant feedback and I hope to continue improving upon the manager. I also would love to see some of the innovative things being produced with the manager, so if anybody wants to show off their stuff, please post it.

Features of the GM2 is:

  • Full transforms available. Position, full 3D rotation, scaling, and depth.
  • Reduce all GUI elements down to one drawcall
  • Use of texture atlas. This can be compressed to save memory
  • Animation system can animate any parameter in the GUI element
  • Frame animation system for sprite animation needs
  • Get callbacks to the GUI element when a touch event occurs
  • Fade in/out individual elements or all elements
  • Tint or shade GUI elements
  • Resize GUI elements dynamically
  • Integrate GUIText and GUITexture to the scene
  • Up to 10 GUILayers to create interesting overlays
  • Support for all 5 touches on the iPhone
  • Works for both iPhone Unity and regular Unity. So code once and build for both.
  • Adjustable sized touch area response for GUI element.
  • Screen resolution independent. The manager is not just for the iPhone anymore.
  • Much simpler setup from previous versions
  • Pixel perfect GUI object collisions. Create crazy shapped buttons and now have them send false touches anymore.

Usage:

  1. Create an empty project.

  2. Import the package into your empty project. You should now get the Plugins, Shader, Textures folder, etc…

  3. Create a game object and name it “GUI”. Attach the GUIManager script from the Plugins folder to this object. Set the screen resolution. This is the main GUI system. If you wish to use the iTouch script for development on Unity Standard, attach that script to the object also.

  4. Create a game object under the “GUI” object just created. This is going to be the quad manager. Attach the GUIQuadManager script from the Plugins folder to this object. Set the position and rotation to 0,0,0. Set the scale to 1,1,1.

  5. Create a new game object and make it a child of the quad manager. Set the position and rotation to 0,0,0. Set the scale to 1,1,1. Attach the GUIQuadObject script to it from the Plugins folder.

  6. Fill out the setting in the inspector for the quad manager:

  • Material - Create a material with the texture atlas and use the ‘GUIManager’ shader or the ‘GUIManager with Backface’ shader if you need to render both sides of the quad. You’ll find the shaders in the GUIAssets->Shaders folder.
  • Alloc Block Size - You can set to to whatever you want. It just has to be 1 or more. This is amount of memory to allocate after all memory from the previous allocation is used up.
  1. Fill out the settings in the inspector for the child:
  • MColor – Set the tint and alpha for the gui object.
  • MWidth - The width of the gui object
  • MHeight - The height of the gui object
  • MLocation - The initial location on the screen this gui object should be at. The anchor is in the middle of the gui.
  • MRotation - The initial rotation of the gui object.
  • MScale - The initial scale of the gui object.
  • MUV - The lower left UV coords of the texture map to skin this gui object.
  • MDepth - The layer order. Larger value objects gets placed further back.
  • MAnimUV – This is the UV coords for the first frame in a sprite animation filmstrip.
  • MAnimCols – The number of columns for the sprite animation filmstrip.
  • MAnimMaxFrames – The total number of frames in the sprite animation.
  • MCollider - You can select None, Square or Circular hit areas used for touch inputs.
  • MCollider Size – Size of the touch area associated with this gui object.
  • MVisible - Is this gui object visible
  • MEnabled – Determine if the gui object will response to inputs like the mouse or touches.
  1. Make sure to select the layer value of the parent and all the children to the render on the GUILayer you want.

  2. Turn off the layers you created in the main camera under the Culling Mask settings. The layers you created should be unchecked.

  3. Create the gui handler script. This script handles the callbacks from the manager. You will do all your app logic here. Attach this also to the child object. You should now have a single gui object on the screen when you run the project. Please check out the sample scene included in the package to see how the manager can be used.

Reference:
GUIQuadObj Class:
This class handles the quad for all the GUI elements. It communicates with the GUIQuadMgr to merge all the elements into a single mesh.

Parameters:

  • GUIQuadObj.QuadManager: Gets a pointer to the GUIQuadMgr this object is attached to.
  • GUIQuadObj.QuadSprite: Gets a pointer to the GUISprite class used internally.
  • GUIQuadObj.Tint : Set/Get the objects color.
  • GUIQuadObj.Width: Set/Get the objects pixel width.
  • GUIQuadObj.Height: Set/Get the objects pixel height.
  • GUIQuadObj.Location: Set/Get the objects location on the screen in pixel coordinates.
  • GUIQuadObj.Rotation: Set/Get the objects rotation in degrees. You can do rotation on all three axis. To get rotation with perspective, set the camera under the master GUI object to perspective. Otherwise, you’ll get orthographic rotations.
  • GUIQuadObj.Scale: Set/Get the objects scale. One unit represent on width/height value of the object.
  • GUIQuadObj.UV: Set/Get the UV coordinates for the lower left corner of the quad.
  • GUIQuadObj.Depth: Set/Get the layer depth of the object. Larger numbers places the object farther back.
  • GUIQuadObj.AnimUV: Set/Get the UV coordinates of the start of the sprite animation filmstrip.
  • GUIQuadObj.AnimCols: Set/Get the number of columns in the sprite animation filmstrip.
  • GUIQuadObj.AnimMaxFrames: Set/Get the total number of frames in the sprite animation.
  • GUIQuadObj.Visibile: Set/Get the objects visibility.
  • GUIQuadObj.Enabled: Set/Get whether the object responds to input events.

Methods:

  • void GUIQuadObj.StartFPS (int StartVal, int EndVal, float Speed, FrameMode AnimMode)
    This functions start the sprite frame animator. The start frame, end frame, and FPS is used to control the animation. The FrameMode determines the playback type:

  • GUIQuadObj.FrameMode.ForwardOneShot – Animated forward once and stop.

  • GUIQuadObj.FrameMode.ForwardLoop – Animate forward looped

  • GUIQuadObj.FrameMode.BackwardOneShot – Animated reversed once and stop.

  • GUIQuadObj.FrameMode.BackwardLoop – Animate reversed looped

  • GUIQuadObj.FrameMode.Bounce – Animate frames back and forth, looped

  • void GUIQuadObj.StopFPS ()
    Stop all sprite frame animation.

  • void GUIQuadObj.AnimateTo (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUI parameters from the current state to the desired state then call the specified callback function.

  • void GUIQuadObj.AnimateFrom (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUI parameters from the desired state to the current state then call the specified callback function.

  • void GUIQuadObj.AnimateBy (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUI parameters from the current state by the amounts in the desired state then call the specified callback function.

  • void GUIQuadObj.StartAnimation (Animate Mode, GameObject CallbackObj, object CallbackMsg, object CallbackParams)
    Starts a series of buffered animation commands then call the specified callback function. Use Ani.Animate.OneShot or Ani.Animate.Loop for the mode.

  • voidGUIQuadObj.StopAnimation ()
    Stops the current animation, but does not clear the buffered animation sequence.

  • voidGUIQuadObj.ClearAnimation ()
    Clears all buffered animation commands.

  • void GUIQuadObj.UpdateTransform ()
    Updates the vertices of the object if it has moved due to changes in the transform of itself or any of its parents. You must call after changing any of its parents transforms to re-sync the object with the new world coordinates. If you don’t do this, the hit areas and the paint area will be in the wrong place.

Callbacks/Events:

  • onGUIUp (iPhoneTouch pTouch)
  • onGUIDown (iPhoneTouch pTouch)
  • onGUIMoved (iPhoneTouch pTouch)

GUITextObj Class:
This class handles the use of the GUIText component. You don’t need to use this as you can directly handle GUIText components yourself, but I’ve already created a buffer of GUIText elements and this class is the interface. By using this interface, you won’t have to create and destroy GUIText components all the time. You can just keep reusing them.

Parameters:

  • GUITextObj.GameObj: Gets a pointer to the gameobject this GUIText component is attached to.
  • GUITextObj.TextObj: Gets a pointer to the GUIText component.
  • GUITextObj.GUIActive: Set/Get the flag to determine if the GUIText is being used by someone.
  • GUITextObj.Text: Set/Get the text string for the GUIText.
  • GUITextObj.Location: Set/Get the pixelOffset for the GUIText.
  • GUITextObj.LocX: Set/Get just the pixelOffset.x parameter.
  • GUITextObj.LocY: Set/Get just the pixelOffset.y parameter.
  • GUITextObj.GUIDepth: Set/Get the Z transform parameter. This also sets the layering order for the GUIText. The larger the number is closer to the camera it is.
  • GUITextObj.TextMaterial: Set/Get the material use for text rendering.
  • GUITextObj.Enabled: Set/Get whether the GUIText is active.

Methods:

  • void GUITextObj.SetFormat (Font pFont, TextAlignment pAlign, TextAnchor pAnchor, float pSpacing, float pTabSize)
    This function sets up all most of the GUIText parameters.

  • void GUITextObj.Reset ()
    This function releases the GUIText from usage and makes it available for reuse.

  • void GUITextObj.CheckHit (Vector3 Coords)
    This function checks to see if the user clicked on the component. Pass the mouse input values.

  • void GUITextObj.AnimateTo (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUIText parameters from the current state to the desired state.

  • void GUITextObj.AnimateFrom (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUIText parameters from the desired state to the current state

  • void GUITextObj.AnimateBy (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUIText parameters from the current state by the amounts in the desired state.

  • void GUITextObj.StartAnimation (Animate Mode, GameObject CallbackObj, object CallbackMsg, object CallbackParams)
    Starts a series of buffered animation commands. Use Ani.Animate.OneShot or Ani.Animate.Loop for the mode.

  • voidGUITextObj.StopAnimation ()
    Stops the current animation, but does not clear the buffered animation sequence.

  • voidGUITextObj.ClearAnimation ()
    Clears all buffered animation commands.

GUITextureObj Class:
This class handles the use of the GUITexture component. You don’t need to use this as you can directly handle GUITexture components yourself, but I’ve already created a buffer of GUITexture elements and this class is the interface. By using this interface, you won’t have to create and destroy GUITexture components all the time. You can just keep reusing them.

Parameters:

  • GUITextureObj.GameObj: Gets a pointer to the gameobject this GUITexture component is attached to.
  • GUITextureObj.TextObj: Gets a pointer to the GUITexture component.
  • GUITextureObj.GUIActive: Set/Get the flag to determine if the GUITexture is being used by someone.
  • GUITextureObj.Image: Set/Get the texture for the GUITexture.
  • GUITextureObj.Location: Set/Get the pixelInset for the GUITexture.
  • GUITextureObj.LocX: Set/Get just the pixelInset.x parameter.
  • GUITextureObj.LocY: Set/Get just the pixelInset.y parameter.
  • GUITextureObj.LocW: Set/Get just the pixelInset.width parameter.
  • GUITextureObj.LocH: Set/Get just the pixelInset.height parameter.
  • GUITextureObj.GUIDepth: Set/Get the Z transform parameter. This also sets the layering order for the GUITexture. The larger the number is closer to the camera it is.
  • GUITextureObj.Enabled: Set/Get whether the GUITexture is active.

Methods:

  • void GUITextureObj.Reset ()
    This function releases the GUITexture from usage and makes it available for reuse.

  • void GUITextureObj.CheckHit (Vector3 Coords)
    This function checks to see if the user clicked on the component. Pass the mouse input values.

  • void GUITextureObj.AnimateTo (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUITexture parameters from the current state to the desired state.

  • void GUITextureObj.AnimateFrom (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUITexture parameters from the desired state to the current state.

  • void GUITextureObj.AnimateBy (float Duration, GameObject CallbackObj, object CallbackMsg, object CallbackParams, params object[ ] args)
    This function animates the GUITexture parameters from the current state by the amounts in the desired state.

  • void GUITextureObj.StartAnimation (Animate Mode, GameObject CallbackObj, object CallbackMsg, object CallbackParams)
    Starts a series of buffered animation commands. Use Ani.Animate.OneShot or Ani.Animate.Loop for the mode.

  • voidGUITextureObj.StopAnimation ()
    Stops the current animation, but does not clear the buffered animation sequence.

  • void GUITextureObj.ClearAnimation ()
    Clears all buffered animation commands.

258799–9300–$gm2_100202_129.unitypackage (112 KB)

Some have asked what the sample scene is suppose to demonstrate. I know the scene look quite odd with a bunch of object just doing weird things. Well, the sample scene demonstrates some of the feature of GM2. In the scene hierarchy, there are two quad managers and six quad objects. Below describes what they’re demonstrating:

TestObj1:

This is the oval PLAY object that rotates back and forth. The script attach demonstrate the animation of the transform parameters and the color transparency. The Location, Rotation, and Color parameters are being animated. Also, this script show how to create a new GUIText and GUITexture object and animate them too. Total draw calls here is 3. One for the quad, one for the GUIText, and one for the GUITexture.

TestObj2:

This demonstrates sprite animation. It is the happy face eating the lollipop. The script show how to start the animation and keep it looped. Check out the texture to see how the frames are laid out. No drawcall is added.

TestObj3:

This object is attached to the 2nd quad manager and is the large rectangular PLAY sprite in the middle of the screen. This demonstrates 3D rotations and depth control. As you can see, the object is near pixel perfect and had perspective while rotating. In order to achieve the perspective, we had to set the camera to perspective mode and therefore we needed to render on a different layer. Because a new layer was used, one drawcall was added.

TestObj4, TestObj5, TestObj6:

These three objects are the circular X sprites. This set of icons demonstrates pixel perfect collision. No input events are sent unless the mouse is within the icons. Also, even though they overlap, the correct event is returned. No drawcalls are added.

So, if I add up all the drawcalls:
+1 QuadMgr1
+1 GUIText
+1 GUITexture
+1 QuadMgr2
= 4 drawcalls.

This may still seems like a lot, but this is just a demostration. You can decide not to use GUITextures or 3D rotations and get the calls down to 2. And if no text is needed, it’ll be just one call.

Is me again :smile:

I was reading through entire source for QuadManagers, but i couldnt found SetActiveRecursively action? how do I set active state to open and close if i have separated QuadManager to manage 3 different menu.

As for my understanding, I need to create 3 Quadmanagers like ur example project shows. but how to it hide another 2 quadmanagers when i press the 1st quadmanagers?

Great help would be appreciate :slight_smile:

Let’s assume the hierarchy is like this:

QuadMgr1
Scr1Obj1
Scr1Obj2

QuadMgr2
Scr2Obj1

QuadMgr3
Scr3Obj1

In script assigned to QuadMgr1, you should do this:

Awake()
{
GUIQuadMgr screen2 = (GUIQuadMgr) GameObject.Find(“QuadMgr2”).GetComponent(typeof(GUIQuadMgr));
GUIQuadMgr screen3 = (GUIQuadMgr) GameObject.Find(“QuadMgr3”).GetComponent(typeof(GUIQuadMgr));
}

Then to turn off the screen2 and 3 when a button is clicked:

onGUIDown ()
{
screen2.SetActiveRecursively(false);
screen3.SetActiveRecursively(false);
}

That’s it. SetActiveRecursively is a Unity function and not a GM2 function.

I used GM1 for Waddlefield, and I’m using GM2 for my second 2d sprite game. It is amazing. With this animation feature, the environment and characters have really come alive!

It does take a little time to figure it out, but once you do, this tool is invaluable.

I am looking for a way to display a curved health bar that changes descent angle as health decreases.

I am trying to find a way to create the equivalent of a layer mask so that when the health bar rotates, I mask the part of the health bar that would show up under the health frame and obstruct the scene view.

Any suggestions? Someone on IRC suggested that I look into camera depth clearing to achieve this, but I don’t really understand how to apply that technique.

Are you interested in using the GM2 to do this? If so, can you show a picture of what you’re trying to do so I can better understand it?

Any special tips for upgrading a project from GM1 to GM2?

iByte

Hi besuser,

Great work on GM2. We are still trying to evaluate whether I can use GM2 for our needs.

We are trying to make an in game GUI, basically this GUI is a computer screen that has text that would change depending on various factors. I was wondering whether or not it would be possible to leverage GM2 to achieve the results we are after?

If it can do what we are after, do you know of any examples that would assist me?

I’m hoping to accomplish this with GM1 if possible. GM2 is an option as well, but I haven’t tested with GM2 yet.

I’ve attached a quick mockup of what I’m trying to do in a png as well as a zip containing a layered PSD of the sample. Thanks for looking at this!

260516–9361–$mask_263.zip (46.5 KB)
260516--9362--$mask_160.png

@iByte. Unfortunately, from version to version, there are differences. For the most part, the core of GM2 is not that much different from GM1. Most of the changes are syntatical and could be easily fixed depending on how large your application is. My suggestion would be to delay upgrading till your next project if GM1 is working good for you.

@nathanp812. If you just want a background that looks like a computer terminal with text overlaid, then that will certainly work. I have even used user created fonts which would sell the computer terminal idea even more.

@azterix. That’s a tough one. You could possibly cut the arc into sections instead of trying to rotate it. It’s not ideal of course, but I don’t think you can do what you’re proposing with any sprite based system. Another possibility is to use a 3D triangle and modify it’s verticies to make the meter look like it’s draining. With the GM2, you can mix true 3D object with quad based objects. You just need to attach the object to the correct User Layer.

First of all thanks besuser for your effort and time.

Sorry if this has been asked and answered before: I would need to display a lot of texts in my RPG project (character screen with a lot of stats and numbers). I need to load the strings from an external file (for localization purposes) and use a bitmap font to render the texts.

Does GM2 speed up text drawing too (reducing drawcalls)? What method should I use? GUIText or TextMesh or something else?

Andrej. Unfortunately, I don’t know of any solution for reducing drawcalls on text. It is theoretically possible to do it, but the task is not simple. You have to create your own text system in a sense. First create a font map with the proper UVs for each letter. Then, create quads for every letter to be draw on the fly using the UV and combine them into a single mesh. This will produce the text you want with a single drawcall. Of course, there still a little more to it than that, but that kinda where you’d need to go.

As for using GM2, it basically uses GUIText. There is no drawcall savings. TextMesh is only useful if the text needs to have perspective, otherwise, GUIText is easy and display correctly for 2D use.

Thank you for the clarification, and for the detailed tips, I really appreciate it. Seems like I’ll stick with GUIText for now. Have a nice day :wink:

This looks pretty amazing… where do we get the files and sample projects these days?

Login to the forum and you will see the download link in the main post.

iByte

Hi There,

First, the GUIManager is a real help and thanks for it.

I am looking to use ElasticEasing .

ptrImage.AnimateTo(0.7f, null, null, null, “LocY”, 300f, “easing”, Ani.AnimationEasingType.ElasticEasing);

I have a noob question…I don’t find how to set the call with an Out or In parameter ? I need some help here…

Thanks

ptrImage.AnimateTo(0.7f, null, null, null, “LocY”, 300f, “easing”, Ani.AnimationEasingType.ElasticEasing, “direction”, Ani.EasingType.In);

You can use:

Ani.EasingType.In
Ani.EasingType.Out
Ani.EasingType.InOut

Try it,Great~

Thanks to you… :)) it’s great…great…