I've run through an entire fault tree trying to diagnose this, with no joy.
I'm writing a 2D card game in Unity/C#. I have four panels (one per player) that hold the cards, name, discard pile, etc. for each player. I need to have a pop-up dialog panel come up over the player panels when the user wants to change options. For some reason, I cannot get the pop-up to appear over the card sprites (it does appear over the other elements: interior panels, images, text boxes, etc.). I've tried adjust the Zpos for the dialog box panel, but nothing changes. That's problem one, but it leads to a more worrisome issue.
The bigger issue is this. Since the options panel won't display in front of the players' cards, I thought I'd just deactivate the player panels, display the dialog, then deactivate it and re-activate the player panels when it's closed. That works fine: for three of the panels. The fourth panel comes back on in its previous state, but the graphics on it will no longer update.
I've debugged and discovered the new cards are being handled correctly (sprite names changing, etc.), the discard pile is being updated, the player's name is being highlight/de-highlighted as the game progress, but none of it is appearing! It's visually stuck in the state it was when I deactivated it.
Investigating further, I've determined the error crops up anytime I deactivate and the re-activate that player's panel, whether I do it via the inspector (attaching those events to a button click), or do it in-line in script. I don't even have to open the options dialog box: I put SetActive(false/true) statements in my game code and it immediately kills the graphics updating for that panel. The sprites, text, etc. remain as they were when I deactivated and will not update.
player3Obj.gameObject.SetActive(false)
player3Obj.gameObject.SetActive(true);
Doing that to the other three panels has no effect and works fine. I see nothing different about panel 4. In fact, I can deactivate only one of its card sprites, and when I turn it back on, it is now "stuck" and won't update, even though all the other cards in that player's hand will. Same if I deactivate/re-activate one of the text fields. It will no longer update, but everything else does.
I've got no exception errors or anything, but this looks to me like some kind of memory problem, though I can't imagine what. It shows up in my Android build, no it's not specific to my machine. I'm throwing this question out there hoping someone has seen something similar.
If nothing else, maybe someone can tell me how to get my options panel to display over the card sprites. But I hate to leave a problem undiagnosed: they have a way of coming back and biting.
Update
Here's the code that isn't getting displayed. The cardBackSprit values are updating correctly, as is the gameObjectSprite, but the image onscreen isn't changing:
void DrawCardBitmap2(int Player, int cardSpot, int cardIndex)
{
string spriteObjectName;
spriteObjectName = "Sprite_Player" + Player + "_" + cardSpot;
gameObjectSprite = GameObject.Find(spriteObjectName);
gameObjectSprite.GetComponent<SpriteRenderer>().sprite = cardBackSprite;
}
There's a lot to unpack here. Let's break down your post into a series of questions:
1. I cannot get the pop-up to appear over the card sprites
It sounds like you're using the UI Canvas in Unity to handle your info panels for your players, but gameObjects for other elements. This is good, but the UI Canvas' sorting order is a bit different from standard game objects.
UI elements in the Canvas are drawn in the same order they appear in the Hierarchy. The first child is drawn first, the second child next, and so on. If two UI elements overlap, the later one will appear on top of the earlier one.
In order for your pop-up to appear above other elements in your canvas, they need be be higher in your scene's Canvas hierarchy.
Important to note: Canvases set to any Screen Space render mode will render over other game objects in the scene. Canvases set to World Space will render in their world position in the scene. The only render mode that uses Z Position to choose sorting order is World Space, but this is not my recommended solution to your problem.
My recommended solution:
Break your UI into multiple different canvases. Specifically, move your pop-up to a different canvas and place it higher in the scene hierarchy than your card sprites. When you enable/disable or move the pop-up, it will now appear over the card sprites.
2. Four panels (one per player) that hold the cards
From context and some of your code, it sounds like you have SpriteRenderers in your UI Canvas. This is known to be a complex rendering problem. Common advice involves using 2 cameras for rendering, and use camera depth to raise sprites over UI elements. However, redesigning your UI canvas is probably simpler.
3. Using GameObject.Find and complex strings at runtime
GameObject.Find is not performant, and it's not robust. It looks through all elements in the scene and returns the first object it finds with that name.
This poses a few problems:
You cannot have game objects with the same name anywhere in your hierarchy, even if they are nested in different places.
CPU cycles are wasted searching through all objects.
Hidden dependencies on object names that only show up during runtime.
Here's a great blog post on some better practices. I recommend using the [SerializeField] attribute and configuring it via inspector.
4. Canvas isn't updating when objects inside of it change
You can consider invoking Canvas.ForceUpdateCanvases() in LateUpdate(). This is more of a hack than an actual solution, but if this solves your problem it is likely an issue with canvas rendering. If this does not solve your problem, then this problem is likely elsewhere in your code that is currently not provided.
A canvas performs its layout and content generation calculations at the end of a frame, just before rendering, in order to ensure that it's based on all the latest changes that may have happened during that frame. This means that in the Start callback and the first Update callback, the layout and content under the canvas may not be up-to-date.
Related
I have a question regarding Unity and mrtk. I need to create an object, which can be deleted via button push. This button should be attached to the object. Now there is the app bar which can be attached to the object and which is very convenient because the buttons are only displayed on the side of the object you currently look at. However the app bar does not seem to work properly with the new bounding box and after deactivating the adjust button on it. So my question basically is, how do i make a button which is attached to the object, hovers on it and is only displayed on the side of the object i am currently looking at? The script of the app bar is very poorly commented, so i cannot figure out which part is responsible for making the button appear on the correct side and correspondingly how to write a script displaying the delete button only on the correct side (following the direction i am currently looking at).
To solve this problem you need a free Canvas that attaches to your object. This Canvas should be adjusted to the dimensions of the object and always look at the camera. To do this, first create a canvas and set RenderMode to World Space, Remember that you have entered the Event camera reference.:
After completing the canvas, make a button like the one below and place it in the body. In this section, adjust the dimensions so that you want to appear in near of your main object.
Finally, I suggest using Look At Constraint to match the canvas and the view to the camera. Insert the camera as source and fix Constraint settings it as shown below.
Example Result
I have no idea why this happens and I was wondering if there was a reason or maybe even a fix.
Vid link to what I'm talking about: https://youtu.be/HwxqL95lzXU
The reason it occurs is that the editor has to update all changes made on whatever you have selected. On top of that, Unity will attempt to draw the gizmos related to the object you have selected and all child objects. Depending on the object you have selected, the number of updates that need to redraw the editor and/or the number of gizmos needed to be drawn can take up a lot of CPU, which causes lag.
The one solution I can think of is to click on Gizmos in the top right of the editor window, and uncheck the box Selection Outline. If there is not a noticeable enough difference, disabling all gizmos can also help.
Outside of these small changes, I am unsure if there is a way to heavily reduce CPU usage in editor when selecting objects in editor. I tend to never have objects selected while playing unless I need to track various data. Even if I do need to track data, it is not the entire gameObject, so I will selectively print data I need or track it with a custom editor tool.
My team has made an application in Unity3D with MRTK for the Hololens 2. Our main menu inside the application does not use a Canvas, but includes Quads to display pictures and Text Mesh Pro's 3D text fields. I have found that, while this menu is open, several elements like the top-left corner picture and part of the text fields are jittery when you hold your head steady. When you nod your head, the affected parts of the text seem to lag behind so that they end up lower or higher than the text that remains steady.
The cutoff point between stable and unstable text is always the same. There is a central area that is stable. Text that is too high, or too far to the left or right in unstable. The division is in the middle of the letters (For example, the top-most part of the capital letter S is unstable, while the smaller letter m is stable.) It does not matter if the viewport is centered on the center or the side of the menu. Other objects in the menu, such as buttons, that are further outside the center, are still stable.
I'm aware that there can be problems with hologram stability, but I do not understand why only part of the same textfield are affected. I can't include screenshots or videos because the effect doesn't show up in screencaptures of the Hololens.
Does anyone know what could be causing part of an object to be unstable in the Hololens, and what might be done about it?
Edit: I made an edited screenshot to try and recreate the visual effect seen in the Hololens:
It seems to be related to depth reprojection. Text doesn't write to the depth buffer by default, which can lead to instability. MRTK have some tips, including specifically for TMPro:Depth buffer sharing in Unity
I'm quite new to Unity, so I'm sorry if this is a basic question. I've been trying to set up the UI for a mobile game, but I'm not quite sure how to make the UI lock it's position, no matter the screen size. I've tried using anchors (though I don't fully understand how to use them properly), I've tried using a canvas scaler, I've looked at the Unity document and I just can't seem to find an answer. The buttons are off screen/half off the screen when I build the game to my device/switch screen sizes in the game view. Does anyone know how to fix this?
You can set your anchor point by selecting the UI object (such as a button) and then clicking here and selecting the right anchor point. You can also press down shift to set the pivot and/or alt to move the object to that point at the same time. The object should now be anchored to that point and keep its position even if the resolution is changed. You can set a precise position from the inspector, too. Simply adjust the Pos X and Pos Y variables. It will still adhere to the anchor point.
Note that you might have to play around with the Canvas object's UI Scale mode and its settings to get the right setup.
I'm making a presentation of someone using the Hololens that is duplicated on a big screen. For duplication it uses the device portal's mixed reality capture option (live stream).
I need to render a tool tip to be visible only to the person with the Hololens - but invisible to the people watching it on the big screen.
From what I've seen, the only difference in rendering between the two is that I can render black on the live stream (if I omit rendering the alpha channel) with it being invisible on the Hololens due to the way it's screen works. This is unfortunately useless to me, as I need to show something to the Hololens viewer, not big screen viewers.
Any ideas on how can I make part of the content visible only to the hololens user?
I can't use spectator view due to other constraints (I need first person view).
Found a solution, not the best one possible, but usable.
I render the tooltip objects only to the right eye, as only the contents of the left eye are included in the live view.
For anyone wondering, in a shader, there is a magic value of unity_StereoEyeIndex that has the value 1 or 0, depending on the eye. To use this value, it first needs to be set up.
If anoyone has an idea how can I do this without sacrificing stereoscopy, I'll be happy to hear about it.