| View previous topic :: View next topic |
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Thu Apr 30, 2009 3:51 am Post subject: GUIManager |
|
|
|
I’ve been a long time user of Unity and have come to this great forum many of times when I’ve gotten stuck. I must say that this community is the best and most helpful I’ve seen of any game engine site. As I’ve learned so much from the forums, I’d like to contribute back to the community.
One of the most troublesome things about working with the Iphone is the limited drawcalls and memory. For me, most of the optimization is done on the GUI. How to possibly keep the drawcalls down and use less memory. With the inspiration of others on this forum, I’ve come up with a possible solution that hopefully others can benefit from too. Now, this is only my interpretation of one possible solution and it works for me, but it's not by all means the answer to every situation. I give a shout out to the following for their great work:
SpriteManager by Brady
SpriteUI by CedarParkDad
Ani.Mate by Adrian
Features of the GUIManager is:
- 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
- Get callback to the GUI element when a touch event occurs
- Fade in/out individual elements or all elements
- Tint or shade GUI elements
- Realtime depth sorting
- Resize GUI elements dynamically
- Mirroring. This can reduce texture needs by half.
- Make GUI groups by parenting. There no need to be a direct child of the manager anymore.
- Integrate GUIText and GUITexture to the scene
- Layer up to 5 panels to create a windowed effect
- 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. This helps detect touches even when the GUI object is small.
- Pixel Perfect collision for mouse input.
- Dynamic re-orientation when switching from portrait to landscape or vice versa.
Usage:
1. Create an empty project.
2. Download the Unity package.
3. Import the package into your empty project. You should now get the Plugins, Shader, Textures folder, etc...
4. Drag the GUIManager prefab into the hierarchy.
5. Create 10 user layers. Start with user layer 8 and name it GUILayer1. Continue on naming the successive layers GUILayer2, GUILayer3...GUILayer10.
6. In the GUI game object, create a game object. This is going to be the parent. 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.
7. Create a new game object and make it a child of the parent. 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.
8. Fill out the setting in the inspector for the parent:
* Material - Create a material with the texture atlas and use the GUIManager Sorted shader. Apply it here.
* Alloc Block Size - You can set to to whatever you want. It just has to be 1 or more.
9. 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.
* 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
* Enabled - Will the gui object respond to input events
* MFlipped – Is the gui image flipped horizontally
10. Make sure to select the layer value of the parent and all the children to the render on the layer you want.
11. Turn off the layers you created in the main camera under the Culling Mask settings. The layers you created should be unchecked. Otherwise, you double your drawcalls.
12. 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. That should be it. Just run the project and you should see your newly created GUI.
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.
- 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.Enabled: Set/Get whether the object responds to inputs.
- GUIQuadObj.Visibile: Set/Get the objects visibility.
- GUIQuadObj.Flip: Set/Get the objects flipped flag.
Methods:
- 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.
- void GUIQuadObj.StopAnimation ()
Stops the current animation, but does not clear the buffered animation sequence.
- void GUIQuadObj.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 Touch)
- onGUIDown (iPhoneTouch Touch)
- onGUIMoved (iPhoneTouch Touch)
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.
- void GUITextObj.StopAnimation ()
Stops the current animation, but does not clear the buffered animation sequence.
- void GUITextObj.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.
- void GUITextureObj.StopAnimation ()
Stops the current animation, but does not clear the buffered animation sequence.
- void GUITextureObj.ClearAnimation ()
Clears all buffered animation commands. _________________ GamerFuse
www.gamerfuse.com
Brethren Studios
www.brethrenstudios.com
Last edited by besuser on Thu Jul 16, 2009 12:42 am; edited 22 times in total |
|
| Back to top |
|
|
CedarParkDad
Joined: 28 May 2008 Posts: 98 Location: Austin, TX
|
Posted: Thu Apr 30, 2009 4:40 am Post subject: |
|
|
|
Ahhhh...now this is nice. I've been trying to get this to work correctly, and it's nice to see someone else get it done Congrats! I'll play with this a bit and provide some feedback. One word of advice when going forward: do not assume you will get every state you would expect. I would want to redo SpriteUI with that understanding, but I'm in too deep now. Basically, you'll sometimes get a Move without getting and Enter or Down, or just stop getting a touch instead of getting an Exit or an Up. That is why SpriteUI has become such spaghetti code...well, that and I never get that time to go back and clean it up
Thank you for letting us play with this...I'm having fun just playing around now instead of making a game. _________________ Bill Mauer |
|
| Back to top |
|
|
Andrej Vojtas
Joined: 12 Jan 2009 Posts: 37
|
Posted: Thu Apr 30, 2009 12:54 pm Post subject: |
|
|
|
| Very nice, thank you for sharing this! |
|
| Back to top |
|
|
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Thu Apr 30, 2009 6:42 pm Post subject: |
|
|
|
| Thanks all. CedarParkDad, I basically left it up to the user to figure out the touch states. I just do the callbacks in whatever order the touch phases come in. I'm sure this could be update to provide a known sequential path, so I'll have to think about this one. |
|
| Back to top |
|
|
Muckel

Joined: 26 Mar 2009 Posts: 140 Location: somewhere
|
Posted: Thu Apr 30, 2009 7:36 pm Post subject: |
|
|
|
wow man....
much respect !
thank you very much...
now i have again very nice stuff to play with
kerstin  |
|
| Back to top |
|
|
kenlem

Joined: 16 Oct 2008 Posts: 693
|
Posted: Fri May 01, 2009 2:10 am Post subject: |
|
|
|
Perfect! Just what I needed right now. Thanks.
I don't see how to set or update the texture associated with the button. Anyone? _________________ Unity Pro + iPhone Advanced |
|
| Back to top |
|
|
kenlem

Joined: 16 Oct 2008 Posts: 693
|
Posted: Fri May 01, 2009 2:14 am Post subject: |
|
|
|
MUV - phew... I knew it had to be there somewhere. _________________ Unity Pro + iPhone Advanced |
|
| Back to top |
|
|
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Thu May 07, 2009 6:41 pm Post subject: |
|
|
|
| I've updated the GUIManager such that it will create the GUI elements in the order specified by the Depth parameters. As long as the GUI elements are children of the main manager script, just set each childrens depth and the manager will sort them and set them up properly. This will allow you to order them up front, but not re-order then on the fly. |
|
| Back to top |
|
|
blastone
Joined: 07 Apr 2009 Posts: 111 Location: Sydney
|
Posted: Sun May 10, 2009 1:27 pm Post subject: |
|
|
|
I have a question with your tool. I got it up and running ok. I have a button that I have a show and a hide function on. The code is below:
| Code: | using UnityEngine;
using System.Collections;
public class BtnPlayer1 : MonoBehaviour {
private GUIObject thisObj;
void Awake ()
{
thisObj = (GUIObject) gameObject.GetComponent(typeof(GUIObject));
}
void Start ()
{
Show();
}
void Show()
{
thisObj.AnimateTo(0.5f, "location", new Vector2(260f,250f));
thisObj.StartAnimation (Animate.OneShot);
}
void Hide()
{
thisObj.AnimateTo(0.5f, "location", new Vector2(1000f,250f));
thisObj.StartAnimation (Animate.OneShot);
}
void onGUIDown ()
{
SendMessageUpwards ("Hide", null, SendMessageOptions.DontRequireReceiver);
Hide();
}
void onGUIUp ()
{
Debug.Log("Scores Up");
}
void onGUIMoved ()
{
Debug.Log("Scores Moved");
}
}
|
Fairly straightforward, whenever the Hide() function is called though
I get an error
[color=red]ArgumentOutOfRangeException: Less than 0 or more than list count.
Parameter name: index
0
System.Collections.ArrayList.RemoveAt (Int32 index)
GUIObject+<>c__CompilerGenerated0.MoveNext () (at Assets/Plugins/GUIObject.cs:289)[/color]
I have a renamed version of this script on another 2 buttons as well.
My question is how do I have a controllable sequencing of animations?
Cheers
Mark _________________ Cheers Mark Fennell
http://www.blastone.com |
|
| Back to top |
|
|
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Mon May 11, 2009 8:47 pm Post subject: |
|
|
|
| Blastone. Let me check this out and I'll get back to you. In the meantime, just to let you know, the animation sequences are being handle per object using a coroutine. So, the calls to StopAnimation and ClearAnimation could accidentally empty the array before the coroutine returns. This would cause the out of index error. I've been working on fixing this up so I'll let you know. |
|
| Back to top |
|
|
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Tue May 12, 2009 1:38 am Post subject: |
|
|
|
| Hi Blastone. It appears that you called the Hide() function twice in a row. One with the sendMessage command and then a direct call to Hide. This confused my startAnimation function. I've patch the code so that if an animation is in progress, it will return a false when you call startAnimation. This means you'll just need to stop the animation first or let the animation finish before it'll let you start the next set of animations. |
|
| Back to top |
|
|
blastone
Joined: 07 Apr 2009 Posts: 111 Location: Sydney
|
Posted: Tue May 12, 2009 2:20 am Post subject: |
|
|
|
ah, the common trap for young players the double function call. Thanks for the code update, Ill play with it tonight.
While on the feature request pathway:
A "delay" would be awesome....
I'm currently implementing it with an animation call to the same position over a timeframe, but it would be great to have a delay like in the Ani.Mate.To stuff (which you are using)
One thng I did notice what that when I set the mRotation of the GUIObject in a function call of its button control script it didnt rotate. I ended up doing a very fast 0.01s rotation animation on it to rotate it properly.
Anyways congrats on a nice set of tools, its got all my hud stuff down to a single draw call which is just great, and im really really really happy about having a single asset image and just picking the bits I need from that for the buttons and other display items.
Its a lot faster then mapping it all in 3d
now when it maps text that will be even better  _________________ Cheers Mark Fennell
http://www.blastone.com |
|
| Back to top |
|
|
blastone
Joined: 07 Apr 2009 Posts: 111 Location: Sydney
|
Posted: Tue May 12, 2009 10:07 pm Post subject: |
|
|
|
Sorry to ask another question, but Im also having a few issues getting the visible tag to work.....
| Code: |
using UnityEngine;
using System.Collections;
public class Powerup : MonoBehaviour {
private GUIObject thisObj;
void Awake ()
{
thisObj = (GUIObject) gameObject.GetComponent(typeof(GUIObject));
thisObj.location = new Vector2(158f, 240f);
}
void Start ()
{
HideCircle();
}
void Update()
{
thisObj.rotation += 2;
}
void HideCircle()
{
thisObj.visible = false;
thisObj.StartAnimation (Animate.OneShot);
}
void ShowCircle ( string type )
{
thisObj.AnimateTo(0.8f, "scale", 1.5f);
thisObj.StartAnimation (Animate.OneShot);
}
}
|
When I click the MVisible checkbox it turns visibility on and off (but not when running) but Im unable to script it. Did I miss something?
One thing I have also noticed is that when I scale an item down in size, sometimes it leaves a large version of it on the screen towards then end of it. I can package up a demo of that if you like as its a strange one. _________________ Cheers Mark Fennell
http://www.blastone.com |
|
| Back to top |
|
|
besuser

Joined: 09 Oct 2007 Posts: 291 Location: Everett, WA
|
Posted: Wed May 13, 2009 1:27 am Post subject: |
|
|
|
| Yeah, the inspector isn't realtime. I made the variables public so our art guys could do the initial setup of the GUIs. You can only update the varaibles via code. For the visibility, just use GUIObject.visible = true/false. As for the scale issue, I definately like to take a look at it. Thanks for helping me test this. |
|
| Back to top |
|
|
blastone
Joined: 07 Apr 2009 Posts: 111 Location: Sydney
|
Posted: Wed May 13, 2009 1:51 am Post subject: |
|
|
|
I did try controlling the visibility with script using
GUIObject.visible = true/false
where GUIObject is the object in question (see my code above) but without success.
Ill package you up a version with that scaling bug as well. Im happy to help you out its a pretty sweet little tool, and fun too.
And I'm more then happy to throw requests to ... easing perhaps! _________________ Cheers Mark Fennell
http://www.blastone.com |
|
| Back to top |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|