Tasharen Entertainment Forum

Support => NGUI 3 Documentation => Topic started by: ArenMook on November 20, 2013, 08:56:37 PM

Title: UISprite
Post by: ArenMook on November 20, 2013, 08:56:37 PM
Overview

UISprite is the bread-and-butter of NGUI. It's a drawn sprite pulled from a texture atlas. Like other widgets, it inherits all the functionality of the UIWidget (http://www.tasharen.com/forum/index.php?topic=6702).

(http://www.tasharen.com/ngui/uisprite.jpg)
Choosing the "Make Pixel-Perfect" option from the context menu will make the UISprite assume its original size. So if the source texture was 300 by 200 pixels, the width and height of your UISprite will be adjusted to exactly those dimensions. Note that this will not be the case with Tiled and Sliced sprites -- they have their own set of rules.

Pro-Tip #1

NGUI will automatically use the last selected atlas and sprite when creating new ones. This means if you have the Atlas Maker open and choose some sprite within, you can quickly create it by hitting ALT+SHIFT+S. Although note that duplicating the selected object is even easier (CTRL+D).

Pro-Tip #2

To change the sprite via code, use its spriteName:
  1. UISprite sprite = GetComponent<UISprite>();
  2. sprite.spriteName = "Some Sprite";
Just make sure that "Some Sprite" actually exists in the atlas! It's case sensitive.

Class Documentation

http://tasharen.com/ngui/docs/class_u_i_sprite.html

If you have a question regarding this component or would like me to clarify something, just post a reply here.
Title: Re: UISprite
Post by: zipper on November 28, 2013, 11:39:40 PM
It would be super nice to have a "use antialiasing" option for the fill.
Title: Re: UISprite
Post by: ArenMook on November 29, 2013, 10:43:48 AM
There will be anti-aliasing if your project has it enabled. It's a hardware setting that smoothes edges of geometry. There is no way to smooth it via code without creating a render texture and modifying a render texture instead of simply adjusting vertices like NGUI does right now.
Title: Re: UISprite
Post by: lzt120 on December 29, 2013, 03:00:55 AM
if use the same sprite but in different alpha for example I have for alpha in 25%,50%,75% and 100%  and will this result in performance issue ?
Title: Re: UISprite
Post by: ArenMook on December 29, 2013, 06:47:45 PM
Not sure what you're do that for, lzt120? If it's the same sprite and you just change the alpha infrequently, there is no performance change from something like that. If you change the alpha every frame, then yes, there will be a performance hit. If you overlay the same sprite on top of the other, then you will also get a performance hit but due to something else entirely -- hardware fillrate limitations. It'll only be noticeable on mobile devices, and even then, marginally so.
Title: Re: UISprite
Post by: charliehelman on January 11, 2014, 05:25:39 AM
Is there a way to adjust the dimension sizes of sprites uniformly in the scene view? Before sprites had dimensions, I would just use the unity scale tool, but now this feels like the wrong thing to do (is it?).

I intuitively expected this to happen when holding SHIFT while adjusting size with the handlers, just like in photoshop (like with the free transform tool).

Does this feature exist in the current version of nGUI?

Also, is there a way to enable snapping while adjusting widget sizes? Having this feature currently when moving sprites is fantastic, but while arranging ui layouts I found myself constantly adjusting dimensions, moving to snap to center, adjusting dimensions again just to try and get the alignment to look good. Obviously the widget  unified alignment options in the inspector fix this problem but I usually don't set those up until after I have the widget arranged the way I want. Edit: I now better understand the widget anchoring options (I was using them wrong, lol). I think I understand Anchoring is a separate feature than snapping while scaling (though some use cases may overlap).

Sorry if part of this belongs in the feedback section.
Title: Re: UISprite
Post by: ArenMook on January 11, 2014, 06:34:28 PM
Snapping only works when moving the widget, it doesn't work for adjusting the widget's dimensions.

You can adjust the widget while keeping its proportions by setting its Aspect Ratio to something other than "Free".
Title: Re: UISprite
Post by: charliehelman on January 12, 2014, 12:50:35 AM
You can adjust the widget while keeping its proportions by setting its Aspect Ratio to something other than "Free".
Ah, I see. I messed around for a few minutes with the aspect ratio options earlier but didn't understand why it wasn't working. I must have accidentally set the ratio value, which wasn't clear to me until your response.

Setting the aspect ratio to Free and then back to Width based reverted the ratio value correctly and the sprite then scaled correctly.

Thank you sir.

EDIT: After some more tinkering, I might have discovered a bug which is what caused my confusion.

Swapping out sprites does not update the aspect ratio value. You have to set it to free, to another option, then back to free before the value actually updates. Intuitively I would expect the value to update whenever the sprite is changed.
Title: Re: UISprite
Post by: ArenMook on January 14, 2014, 06:48:45 PM
Changing the sprite won't change the dimensions of the widget either. You have to call MakePixelPerfect() for it to change dimensions.
Title: Re: UISprite
Post by: MoProductions on April 16, 2014, 02:58:44 PM
Hello.  I've used NGUI for a few things in the past but my new project is 100% 2D GUI so I now have to become the master.  I've been fiddling around and can't seem to find answers to my first couple of questions:

1) I'm creating a sprite out of a 640x1136 (iPhone 5) image, but the sprite ends up being 576x1024, even if I click on the "snap" button.  I ended up adjusting the size myself with the dimensions, but even when I try the "make pixel perfect using the context menu" instructions it goes back to 576x1024.  Is there a way to adjust this, and/or does it have something to do with the power of 2 height?

2) I'm not exactly sure how my boss wants to handle screen resizing, but I was when going from 640x1136 (iPhone 5) to 640x960 (iPhone 4) the image would scale down proportionally so that there was extra space on the sides.  I wanted it to scale to fill the screen, which I had done with UIStretch, but the docs say UIStretch is deprecated and to use Widgets and Panels instead.  I've tried everything with those and can't seem to get the same result.  Can you let me know what I'm missing?

Thank you.  Looking forward to mastering this plugin!
-Mo
Title: Re: UISprite
Post by: ArenMook on April 17, 2014, 02:03:04 PM
1. Don't add such large textures to an atlas. Use UITexture to draw them. Also keep in mind that 640x1136 is not a power of two image, so be aware of that. It's rarely a good idea to do this to begin with. It's almost always better to create a composite background, made up from several elements, overlapping to create the desired more complicated looking result. You can save an incredible amount of texture memory this way.

2. Use the anchoring on the widget itself. Anchor only 2 sides (top and bottom), and specify an aspect ratio on the widget (based on height).
Title: Re: UISprite
Post by: Fractalbase on June 21, 2014, 04:46:43 PM
I want to create a UISprite, without the center filled, so that the center has specific dimensions.  What are the dimensions that the sprite should be in order for the center to have dimensions of say 192x192?  Also, is there a way to specify the color of the center (separate from the border)?
Title: Re: UISprite
Post by: ArenMook on June 21, 2014, 07:58:24 PM
I don't understand your question. UISprite without the center filled? What does that mean?

If you're trying to adjust the position of the sprite's center, and it's a sliced sprite, then it's a simple matter of knowing the desired center size (192x192 in your case) and adding the UISprite.border. Note that the border is a Vector4 in the following order: X = left, Y = bottom, Z = right, W = top.
Title: Re: UISprite
Post by: Fractalbase on June 22, 2014, 10:16:52 AM
Sorry for so many questions.  I've added game objects to my scene, and adjusted the hierarchy.  Now my sprites have position x&y values that are way far away (e.g., -20000).  I can't seem to changes these values.  What would cause that?  How can I fix that?
Title: Re: UISprite
Post by: ArenMook on June 22, 2014, 10:44:27 PM
Without knowing what your hierarchy is like I can't comment much. Try creating a UI from scratch and see where you went wrong.

Also never re-parent widgets to some random game object. This is just plain bad. Widgets need to be under the UIRoot (or if you're an advanced user -- under a UIPanel somewhere in your world). Even if you do want to simply to group widgets underneath your UI, use ALT+SHIFT+N to create a child game object underneath the selected object, not a random game object in the middle of nowhere like Unity does when you do it via the GameObject menu.
Title: Re: UISprite
Post by: roid100 on July 07, 2014, 09:50:21 PM
I have one qeustion about Filled sprite.
I would like to use it for arc shape gauge.
When I use "Radial180" for arc shape gauge, deleting shape is not cool. Because it's center is the middle bottom of the image.
When I use "Radial360", it is not cool also. In this case, the center is the middle of the image.
I use the arc type gauge, the center should be the edge of the image. (sometimes it sould be the outside of image)
I wonder if I can customise the center of the fill sprite.
Thank you.
Title: Re: UISprite
Post by: ArenMook on July 08, 2014, 01:23:18 PM
You would have to create a custom widget for something like that. Override the OnFill function and pass your own vertices.
Title: Re: UISprite
Post by: vikti on August 26, 2014, 01:44:57 PM
What is the attributes for the height/width (in widget sub menu) ?
I can't get my eyes on it...

Is it get and set ?
Title: Re: UISprite
Post by: vikti on August 26, 2014, 01:56:33 PM
Arf...

-> UISprite.width inherited from UIWidget

Need a rest...
Title: Re: UISprite
Post by: superbigface on August 28, 2014, 10:11:24 PM
How can I create a two-sided sprite,just like cards in HearthStone ? Then I can see the front side and the back side when I rotate it.
Title: Re: UISprite
Post by: ArenMook on August 30, 2014, 09:31:11 AM
Don't use a Unlit/Transparent Colored shader. Use a one-sided shader, and use two sprites. One for front, another for back.
Title: Re: UISprite
Post by: YukioT on October 21, 2014, 07:29:27 AM
Hello, I have vertical rope sprite that I need to tile vertically, and scale it when changing its width. Is there a built-in way for this or should I extend UISprites?
Title: Re: UISprite
Post by: ArenMook on October 22, 2014, 05:54:37 AM
NGUI will either scale or tile, not both. You will need to code your own widget for something like that.
Title: Re: UISprite
Post by: blulightjr on October 22, 2014, 05:37:24 PM
I just recently updated Unity to 4.5.5 and NGUI to 3.7.4 and I can't seem to find where I can edit the properties of a sliced sprite anymore. It seems to have moved. Can anyone tell me where I can do that?
Title: Re: UISprite
Post by: YukioT on October 23, 2014, 07:10:39 AM
Ok thanks, will do.
Title: Re: UISprite
Post by: ArenMook on October 23, 2014, 03:47:58 PM
I just recently updated Unity to 4.5.5 and NGUI to 3.7.4 and I can't seem to find where I can edit the properties of a sliced sprite anymore. It seems to have moved. Can anyone tell me where I can do that?
Same place they've always been. Select the atlas, choose the sprite, all the options are there.

If you are asking about UISlicedSprite -- a very, very old legacy script, then you need to run the Upgrade Tools and convert all of them to UISprite.
Title: Re: UISprite
Post by: superbigface on November 12, 2014, 10:40:16 PM
Hello,I had a question.I got a picture which looks like a parallelogram.
 ____________________
/___________________/

I use Type.Filled and FillDirection.Horizontal.But when I drag the fillAmount ,I get a picture:
 __________                 __________
/__________|     not    /_________/

if (mFillDirection == FillDirection.Horizontal)
{
   float fill = (u.z - u.x) * mFillAmount;

   if (mInvert)
   {
      v.x = v.z - (v.z - v.x) * mFillAmount;
      u.x = u.z - fill;
   }
   else
   {
      v.z = v.x + (v.z - v.x) * mFillAmount;               (What should I do)?
      u.z = u.x + fill;
   }
}
Title: Re: UISprite
Post by: ArenMook on November 14, 2014, 05:09:48 AM
If you want it to be tilted like that, you should create a custom widget type and feed your own vertices in its OnFill function. Or just keep it simple and make it a sliced sprite with the left and right side being a part of its border.
Title: Re: UISprite
Post by: zs_3718 on November 21, 2014, 03:55:15 AM
Where is FillDirection.HorizontalMid?I can't find it.
Title: Re: UISprite
Post by: ArenMook on November 21, 2014, 09:16:23 PM
There is no such thing as HorizontalMid.
Title: Re: UISprite
Post by: zs_3718 on November 22, 2014, 01:23:06 AM
Maybe someone in my company modified the code...Thank you. :)
Title: Re: UISprite
Post by: eppz! on September 01, 2015, 04:21:56 PM
What is the best way to inactivate a Sprite (a lot of)?

I have a huge bulk (120) of UISprite in a UIScrollView, also have multitude (7) of such scroll views. In the "frontmost" scroll view I use NGUI culling, but the rest of the scroll views should be inactive.

Currently I'm turning GameObjects On / Off. This way the drawcalls gets destroyed, the widgets won't get updated, childrens get inactivated as well. Beside some performance penalty, another drawback here is that I cannot adjust the dimensions / position of inactive widgets this way.

I'm just wondering if turning off Components only, or mark UISprites somehow not to render could be more efficient? Some way to preserve / reuse drawcalls, only mark them not to render?
Title: Re: UISprite
Post by: ArenMook on September 06, 2015, 05:54:13 PM
You can set their alpha to 0. This way their dimensions will update, but they won't be added to draw calls.
Title: Re: UISprite
Post by: eppz! on September 06, 2015, 06:59:21 PM
Wow, thanks!

Does it affect children down along the hierarchy?
Can I spare CPU (Behaviour.Update) this way as well?
Title: Re: UISprite
Post by: ArenMook on September 13, 2015, 06:17:05 AM
UI is cumulative, so setting the parent to 0 hides all children. Update calls will still be called, as will anchoring logic, but drawing/rebuilding logic won't be.
Title: Re: UISprite
Post by: Bobbin on November 04, 2015, 05:32:10 AM
I'm trying to create a tiled sprite and I find that, at least with the version that I have, my options are rather limited.

I would have preferred a way to shrink the sprite in one dimension and tile in another but I've worked around that.

My main problem now is that it seems like it's tiling from the wrong direction. It's tiling from bottom left when I want it to start from the top left. Is there a setting for that that I missed or is this not an option?
Title: Re: UISprite
Post by: ArenMook on November 04, 2015, 01:34:04 PM
You will need to create your own custom widget then. Derive from UISprite and overwrite the OnFill function. Base its logic on UIBasicSprite.TiledFill, but change its origin.
Title: Re: UISprite
Post by: i_am_kisly on May 14, 2016, 08:09:54 AM
Hello
For me it was somewhat surprising that UISprite.spriteName is case-sensitive. While the search is not case-sensitive in the Atlas window. To understand this it took me a couple of hours (after all the documentation on this is not a word). Please correct or documentation or UISprite.spriteName.set.
Title: Re: UISprite
Post by: ArenMook on May 14, 2016, 07:04:43 PM
Code is always code sensitive. The search field is not sensitive merely for convenience.
Title: Re: UISprite
Post by: Dune on October 21, 2016, 12:16:59 AM
Having trouble getting the sprite to change for instantiated sprite.

  1. public void SetCharacterInfo(CharacterInfo info)
  2. {
  3.     this.CharacterInfo = info;
  4.     var image = GetComponentInChildren<UISprite>();
  5.     //var atlas = image.atlas;
  6.     image.spriteName = info.sprite.name;
  7.  
  8.     var label = GetComponentInChildren<UILabel>();
  9.     label.text = transform.name = info.name;
  10. }

Everything else updates alright. I've verified that the atlas is correct, and the names match. Do I have to call a refresh of some kind on the sprite?
Title: Re: UISprite
Post by: Dune on October 21, 2016, 03:44:48 PM
Never mind on that. I was targeting the wrong UISprite. Didn't notice until now that I was losing the parent sprites "Flat Outline."

Here's the updated code if anyone's interested...

  1. public void SetCharacterInfo(CharacterInfo info)
  2. {
  3.     this.CharacterInfo = info;
  4.     var image = GetComponentsInChildren<UISprite>()
  5.         .First(sprite => sprite.transform.name == "Image");
  6.        
  7.     //var atlas = image.atlas;
  8.     image.spriteName = info.sprite.name;
  9.  
  10.     var label = GetComponentInChildren<UILabel>();
  11.     label.text = transform.name = info.name;
  12. }
  13.  
Title: Re: UISprite
Post by: tvhnet on December 16, 2016, 02:03:57 AM
How can I do this both in UISprite at the same time: "Sliced" and "Filled"?
Title: Re: UISprite
Post by: ArenMook on December 19, 2016, 11:28:24 PM
Change its type to Advanced.
Title: Re: UISprite
Post by: tvhnet on December 26, 2016, 03:56:06 AM
There is no option to use "Filled" feature if type is in Advanced mode. It seems to not support in UISprite.

One more question: I have 2 UISprites which have the same sprite name and atlas and put in the same panel. If I set them the same depth, there is only one draw call. But if I set their depth differently, it is 2 draw calls. How to make 1 draw call in later case?
Title: Re: UISprite
Post by: ArenMook on December 26, 2016, 05:14:53 AM
Oh, sorry misunderstood you somehow. No, you indeed can't have both sliced and filled. Advanced mode lets you tile some parts and slice others, but filled will always affect the entire sprite and doesn't mix with the 9-slicing.

If 2 sprites are underneath the same panel, use the same atlas, and there is nothing in between their depths, then they should end up in the same draw call. You can check the draw call tool to see what got in between of your two sprites, and make sure you indeed don't have another panel there somewhere.