UI Canvas Image with UI Buttons - c#

I have UI canvas image with 2 UI buttons. I set as background, that layer. But this layer overlaying my game! How do I it is behind everything?
I want set the second imagem as background.
I am using the UI Canvas because it automatically adjusts to any screen through the anchors.
-

No GameObject in your scene should be under Canvas unless the GameObject is part of the UI. The background image you want to use is not a UI. Your post shows that you only want it as a UI because Canvas automatically adjust the size to match the screen size.
How to fix this with code and without making that background texture part of the UI.
1.Remove/Delete the current Background and the Canvas Object for it. You don't need it.
2.Re-import the background image and make sure that its Texture Type is set to Sprite (2D and UI)
3.Drag it to the scene and rename it to Background. Now put it under Bee GameObject. Bee should now be the parent of the Background texture and the Background texture should be on top of Ground Object.
4.Create a script called BackGroundResizer and put the code below in it. Attach the script to the Background GameObject/Texture.
// Use this for initialization
void Start()
{
resizeSprite();
}
void resizeSprite()
{
SpriteRenderer bgSprite = GetComponent<SpriteRenderer>();
float screenHeight = Camera.main.orthographicSize * 2;
float screenWidth = screenHeight / Screen.height * Screen.width;
transform.localScale = new Vector3(screenWidth / bgSprite.sprite.bounds.size.x, screenHeight / bgSprite.sprite.bounds.size.y, 1);
}
This should solve your current problem for this post. Below describes how to properly setup a UI.
Use different Canvas to separate your UI and group them depending on when they are displayed. Then you can toggle the whole Canvas on/off. Your post before this post shows that you are using image as button and you have a different script attached to two images you are using as buttons. Use Buttons for buttons and image for non-clickable objects. Simple as that. So change those images to buttons.
You don't need the GameOver scene. A GameOverCanvas is fine.
The GameObjects in bold are the parent Objects(Canvas). The ones under that starts with '-' are the child GameObjects.
Step 1:
Create Canvas and name it MainMenuCanvas (First UI to display when game Loads).Create each child button and rename them as below(GameObject->UI->Button):
-playButton;
-settingsButton;
-exitGameButton;
Attach the MainMenuCanvas script to the MainMenuCanvas Object.
Step 2:
Create a Canvas and name it GameCanvas (Displayed during game).Create each child button and rename them as below(GameObject->UI->Button):
-pauseButton
-jumpButton
Attach the GameCanvas script to the GameCanvas Object.
Step 3:
Create a Canvas and name it PauseCanvas (Displayed when pause button is clicked).Create each child button and rename them as below(GameObject->UI->Button):
-resumeButton;
-backToMainMenuButton;
-settingsButton;
-exitGameButton;
Attach the PauseCanvas script to the PauseCanvas Object.
Step 4:
Create a Canvas and name it SettingsCanvas (Displayed when settings button is clicked).Create each child button and rename them as below(GameObject->UI->Button):
-backButton;
Attach the SettingsCanvas script to the SettingsCanvas Object.
Step 5:
Create a Canvas and name it GameOverCanvas (Displayed when Game is Over or player is killed).Create each child button and rename them as below(GameObject->UI->Button):
-playAgainButton;
-backToMainMenuButton;
-exitGameButton;
Attach the GameOverCanvas script to the GameOverCanvas Object.
Step 6:
In the Game scene, make sure that only GameCanvas is enabled. The rest of the canvas should be manually disabled.
Step 7:
In the Menu scene, make sure that only MainMenuCanvas is enabled. The rest of the canvas should be manually disabled.
Once you get this setup correctly, the UI code templates I provided should work. No more UI overlapping each other and you can easily add or remove features.
Your setup should look like the image below.

I recommend that you look into using a separate UI camera. This will allow you to draw only the UI to the second camera and not the Main Camera. You can then Draw that at whatever depth you want relative to everything else. To do this you will have to create another camera and set it's Culling Mask and Clear Flags to only draw the UI and not a skybox.
If you google 'UI camera Unity' there should be a lot more information on doing exactly what you want. This is a relatively common thing to do.

Related

Setting a button's alphaHitTestMinimumTreshold results into no call to Button.OnPointerDown

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.

Put animated prefab as image in button

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.

Problem with calculating touch and gameObject positions on canvas (Screen Space- Camera Render mode)

all!
I'm working with Unity UI elements. Until recently, my canvas was set to Render mode: Screen space - Overlay. I wrote up some code using touch.position to trigger specific events on my screen: I wanted some objects to appear whenever I would touch an object on my smartphone (or touch within a specific radius of it).
I'm tracking my touch position with touch.position and my specific gameObject element positions with a list of positions I create like this:
Vector2 thisPosition = new Vector2(child.position.x, child.position.y);
When I was working with Render mode: Screen Space - Overlay, everything seemed to be working fine in the inspector; but my elements, as they are not part of the UI, weren't displaying.
When I switched to Render mode: Screen space - Camera or World view, though, my distances started being all over the place.
For example, when touching a button, I would log:
Touch position is(341.7, 372.7)
While my button's position would log:
Button's at(0.0, -1.5)
How could I fix this?

Spawn prefab in front of UI Image

I spawn the prefab in a gameobject and that gameobject is a child of UI Image what I'm trying to accomplish is display the prefab infront of a UI Image. I've tried making z position of gameobject to negative but nothing happens. I can't place the sorting layer of UI Image cause it doesn't exist. What should I do? Is this even possible?
Update
Tried adding second camera. I made gameobject layer to SecondCam. Change settings of second camera to depth only and it's culling mask to SecondCam only then it's layer to SecondCam also. Change settings of main camera culling mask to everything except SecondCam. But this doesn't work, Have I done something wrong?
Second Camera settings
Main Camera settings
If your Gameobject is not one of the UI components you may need to give it another layer and render it with another camera with depth property higher than the UI camera.
You can change the sorting layer on prefabs or any object created on runtime.
If your UI canvas is set to screen overlay, then it with ALWAYS render on top. You have to use a screen space or world space UI, along with Dave's answer.

how to convert coordinate between cameras with Unity3D

I have two cameras,
why I have two cameras?
because I want some game object in front of the Canvas so that it could move around, maybe could have some particles if it feels happy etc.. So:
I set up the main Camera with mask option UI and make it in charge of all the UI stuff, and to make sure it does not overlap everything I set the canvas mode "Screen-Space Camera"
I set up another camera and make it capture everything else except the UI stuff.
set their depth so that the main Camera with UI will behind the other Camera.
things go well now, I could see the game object before the UI stuff. Cheers!
But in some case I what to convert the UI element to the point in the world space, So that I could generate some gameObject near the UI element and maybe Tween it to move to another UI Element, let's take collecting Gems as an example.
Usually, I could just do that with following code:
GameObject go = Instantiate(eff_gem);
go.transform.position = Camera.main.ScreenToWorldPoint(p1.GetComponent<RectTransform>().position);
go.transform.DoMove(p2.GetComponent<RectTransform>().position, 1f).OnComplete(()=>{
Destory(go, 1f);
});
The main idea is to instantiate a gem near a button and make it fly to the count panel.
But since I make the canvas "Screen Space Camera" instead of "Screen Space Overlay", all the above code will be a mess. furthermore, I think I have to convert the screen point of the canvas element to the world space by the other camera, But I can't even get the actual pixel position of the canvas element by
p1.GetComponent<RectTransform>().position now.
So How Can I do that?
I have made a demo project to demonstrate the issue.
var p1R = p1.GetComponent<RectTransform>();
Vector3 p1WorldPos = p1R.TransformPoint(p1R.rect.center);
//use p1WorldPos in your other camera

Categories

Resources