I want to create a button that has a custom shape in Unity.
I created a default UI>Button object and set it's Image to the following sprite:
It doesn't show it on this website, but the circle is the only part of this image that is transparent. It's a .png sprite.
When I set this as the sprite for my button, I could click on the entire rect transform of this sprite to activate the button using my button's OnPointerDown() method and un-hide some other sprites around it:
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
Debug.Log("Foo");
}
Each time any part of the sprite was clicked, transparent or not, "Foo" would print.
Now I set the button alphaHitTestMinimumThreshold to 0.5:
GetComponent<Button>().image.alphaHitTestMinimumThreshold = .5f;
And as the docs suggest, I disabled atlassing...
...and enabled read/write for the sprite:
Yet now, when I click the button in my scene.. nothing happens. No matter where I click, "Foo" doesn't print anymore.
Then I tried changing the alphaHitTestMinimumThreshold to a lot of different values. Again, the entire button was not clickable anymore. If I don't touch the alphaHitTestMinimumTreshold at all however, my "Foo" prints again.
Why does changing alphaHitTestMinimumTreshold to any value make my OnPointerDown method to never be called?
So after 12 hours of messing around with all sorts of options, I found out that there were 3+ consecutive issues causing this behaviour.
If you ever run into your transparent buttons not working, be sure to try the following steps:
Make sure read/write is enabled in the texture import settings
Try if setting the Sprite Mode Mesh Type to Full Rect helps (sometimes the button's hitbox is off)
Disable atlassing under Project Settings > Editor > Sprite Packer > Mode
..and finally what did the trick for me: if you're working in a prefab that's nested inside another prefab (say your have a prefab for your button and then another prefab for your UI canvas/contents), remove the nested prefab from the parent prefab (aka remove the button prefab from the UI prefab), and just add it back in again. It was that freaking simple for me.
I triple checked whether my nested button prefab differed from the button prefab blueprint, and it didn't. But somehow, removing it from the UI prefab and adding it back in again solved my problem with a large sprinkle of magic.
With transparency buttons, I found that detection improves when the image is a child of the button object. So hierarchy is Canvas>Button>Image.
I know, old thread, but it came up so heres my solution:
It did all of the suggestions, but it didn't work.
HOWEVER,
What finally worked for me, was TO SPECIFY THE RIGHT SIZE. My game Object was elongated, but the sprite had "preserve aspect ratio" ticked. I just didn't bother to size it properly.
So when you have an image, set the size of the gameObject to the right dimensions.
Related
I created an animated prefab and want to use it as image in button. Is this possible? If not what can I do to insert an animated image in button.
I assume you are talking about showing an animated 3D prefab on top of your button.
If you have a 3D prefab and want it to be rendered on top of a button, you need to setup a separate render chain.
In essence you add a camera, that renders your object to a RenderTexture. Then you use this RenderTexture as source for an Image component on top of your button.
The critical part is setting up the camera and prefab, so that it doesn't render the whole scene, and isn't visible from whithin the scene.
There are many ways to do that, but I think the easiest way is to place the prefab and camera far away from the rest so that they are outside the view range of the main camera.
Just make sure the camera sees the prefab (and only the prefab) and has the render texture setup as render target.
What I want
To create an effect like an slash in my 2D project. For that, I've an image in my assets already, and I want to draw it from top to the bottom, allowing it to be drawn in maybe half a second, progressively.
The idea is to draw it to create the effect of the slash itself, and the progressively mode is to "fit" the slash image itself, imagine the first one of the following link, that would be drawn from left to right.
To achieve that kind of drawing, the only thing that I've found is fillAmount for an Image, combined with the fillMethod.
The problem
The problem is that these methods are for the Image class, that it's not recommended for game drawing but only for UI.
Anyway, I've tried to do it this way, and I've not been able to do it, because the Unity environment didn't let me drag&drop my slash asset into the Image variable that I had created into my script. I thought that it may be because of the type of import, but also trying to import it with the other options resulted in nothing better.
The questions
Just answering one of these questions would solve my situation (or I think so):
How can I make Unity accept my image/asset into my Image object in the script?
Another way to create such effect using Sprite or GameObjects directly?
Method 1: You can use sprite sheet to create a 2D animation
1-1. Prepare a splash effect sprite sheet (an image map contains continuous action image), like
1-2. Change the sprite mode to multiple in inspector window
1-3. Slice the sprites in sprite editor
1-4. Multi-select the sprites and drag into hierarchy window, Unity will ask you to save this animation
1-5. You will get an animation GameObject
Method 2: If you can make it like a circular progress bar, check Radial/ Circular Progress Bar in unity3d
I ought to have a normal map of tiles as below:
But when I load the scene, either switch from another in inspector (e.g. click "scene/menu", then click this scene), or transit into this scene in gameplay (SceneManager.loadScene), sprites get invisible randomly.
Each time some of the sprites get invisible, and the next time the invisible ones may not be the same. I suspect it is something with Unity editor, since this happens even when I'm not in playing mode.
In Debug.Log I definitely find those sprites (not null). They just don't show up. I have to reload sprites / reload the scene in Unity inspector, but the load doesn't persist.
Neither sprites, SpriteRenderer nor GameObject is null.
As below is a snapshot when some sprites invisible (not missing):
Just click another scene and switch back:
I just accidentally checked in 3D mode, Unity editor is randomizing with z axis. The sprites are there, they were just hidden behind background. This can be fixed then.
I have 2 cameras and 1 Canvas, and I want to change the display for the scene to the second camera when pressing a button, and at the same time, change the target display for the Canvas to the second camera as well, and I'm using C#.
I know that I have to use GetComponent<Camera> and GetComponent<Canvas> but i don't know how to set the indexes for these two.
Any help will appreciated.
Rather than changing the index: just disable the one camera and enable the other. There's no point wasting GPU cycles rendering something that can't be seen (which is what a second active camera will do).
As for changing the Canvas target:
Change the canvas's worldCamera property, eg:
canvasGO.GetComponent<Canvas>().worldCamera = cam2.GetComponent<Camera>();
When I first set a particular gameobject in the Canvas element to active, (SetActive(true)), it lags for a good second or so. Sequential activations are instantaneous. Note that this only happens in the standalone player. In the editor, it doesn't lag at all. My guess is obviously that the first time it has to load the asset. However, can I preload this particular asset in any way? I attempted to do so in the build settings under optimization, but that didn't affect anything. And no, I don't have any code in the Start() function or the OnEnable() function of the said gameobject that's being enabled.
The accepted answer is a workaround, not a solution. Keeping hundreds of UI elements loaded is an utter waste of memory.
You should instead divide up your canvases, as written in this wonderful article by Unity. The reason for the lag is Unity's updating all canvas contents, even disabled objects, when you enable an object for the first time. To prevent unused objects from updating, isolate them in a different canvases. You can even put those canvases as children of your original canvas if you wish.
That's expected.The lag depends on how many UI components and GameObjects that are under the hierarchy of the Canvas. There is so much memory allocation and draw calls when SetActive(true) is used on a Canvas or UI component. The fix is simple. Instead of using SetActive(true) for UI, disable the component by modifying the enabled property.
For example, to enable/disable the the Canvas:
Canvas canvas;
canvas.enabled = true; //Enable
canvas.enabled = false; //Disable
Let's say that you only want to disable a Text component under a Canvas, use the enabled property to disable that Text component instead of SetActive(true). The-same thing applies to other UI components.