Bug when dropping off Inventory container or in original slot. #27
Replies: 3 comments 1 reply
-
How I Fixed UI bugsFirst of all, be sure to use VSync, as otherwise, your game may run at insane FPS, using tons of GPU power and resources. Also, this way you will be able to catch bug number 3. Bugs:
Bug 1. The item icon will disappear when dropping the icon into the original slot or off the inventory grid.In m_OriginalSlot.DropItem(); with if (closestSlot != m_OriginalSlot) {
m_OriginalSlot.DropItem();
} Bug 2. The item icon will stop responding to clicks after the first click and when the mouse stays in the same place (it doesn’t move at all).This one was tricky. I had a bunch of ideas of why that might have been happening and I searched on the internet a lot. I even switched to a new input system, because I thought that the old one might have a bug that prevents clicks from going through if the mouse hasn’t moved. All my searches were in vain. Until I fired up Now was the challenge to pass the second click to the InventorySlot. This is by no means the best approach for a fix, but it’s the best I currently discovered and it works. The main culprit is that In the
to and in
to Then open
Right-click on Save file. This fixes the bug but introduces a new one. The main reason for this is that Fix for the new bug.There are two approaches you can take. Easy fix. First, one is easy but requires you to set dimensions of You can introduce a variable at the beginning of the class and initialize it with size values of private static Vector2 m_GhostIconDimensions = new(128f, 128f); and then use it instead of
in //Set the new position
m_GhostIcon.style.top = position.y - m_GhostIconDimensions.y / 2;
m_GhostIcon.style.left = position.x - m_GhostIconDimensions.x / 2; and in m_GhostIcon.style.top = evt.position.y - m_GhostIconDimensions.y / 2;
m_GhostIcon.style.left = evt.position.x - m_GhostIconDimensions.x / 2; Hard fix. If you want to initialize Create a new method private void InitGhostIconDimensions() {
m_GhostIcon.schedule.Execute(() => {
m_GhostIcon.style.display = DisplayStyle.Flex;
m_GhostIcon.schedule.Execute(() => {
m_GhostIconDimensions = new Vector2(m_GhostIcon.layout.width, m_GhostIcon.layout.height);
Debug.Log(m_GhostIconDimensions);
m_GhostIcon.style.display = DisplayStyle.None;
});
});
} and call it at the end of an InitGhostIconDimensions(); Note: for some reason in my original code, it works even this way. I used bold for a code, that was modified. private void InitGhostIconDimensions() {
m_GhostIcon.schedule.Execute(() => {
m_GhostIcon.schedule.Execute(() => {
**m_GhostIcon.style.display = DisplayStyle.Flex;**
m_GhostIconDimensions = new Vector2(m_GhostIcon.layout.width, m_GhostIcon.layout.height);
Debug.Log(m_GhostIconDimensions);
m_GhostIcon.style.display = DisplayStyle.None;
});
});
} Bug 3. The item icon will stop following the mouse cursor when the mouse moves very fastUsing UI Toolkit debugging tools I found out that when the cursor moves too fast it leaves the area of the My ideas for fixing this bug were:
Until I accidentally stumbled upon a Here is a description from the Documentation: When a VisualElement captures a pointer, all pointer events are sent to the element, regardless of which element is under the pointer. Unity - Scripting API: UIElements.PointerCaptureHelper.CapturePointer That’s exactly what I needed! In the m_GhostIcon.CapturePointer(evt.pointerId); so it looks like this private void OnPointerMove(PointerMoveEvent evt) {
//Only take action if the player is dragging an item around the screen
if (!m_IsDragging) {
return;
}
**m_GhostIcon.CapturePointer(evt.pointerId);**
... and in the m_GhostIcon.ReleasePointer(evt.pointerId) almost at the end. **m_GhostIcon.ReleasePointer(evt.pointerId);**
//Clear dragging related visuals and data
m_IsDragging = false;
m_OriginalSlot = null;
m_GhostIcon.style.display = DisplayStyle.None;
} There are a lot of other bugs to be fixed and improvements that can be made. Although this all may look intimidating at first I didn't know where to even begin to search for how to fix these bugs. It took me on and off about 1.5 days to find all this. |
Beta Was this translation helpful? Give feedback.
-
I'm not %100 percent sure this is the right way but I found another way to fix bug 2. Your answer helped me think about the problem and why the GhostIcon was not an issue when we have not started dragging it. I believe it's because before dragging the GhostIcon, its position is not under the pointer but somewhere in the middle of the inventory content window. Then when we click an icon, the GhostIcon positions itself underneath our cursor and never return to its origin. We could return the GhostIcon to its original position on PointerUp(), which I did, and this works perfectly. Maybe we could also move it to a lower layer so it does not block anything and bring it forward when we need it! (not tried though!) Thanks again, if this helps, then just right a little thank you note to your friend DragonAngel1st (www.dragonangel.com) Cheers, Patrick P.S. Could we also bring it bring it in programmatically using Addressables. I have another UI project that I'm using Addressables and I'm going to try it there. |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot, I had figure bug 1 and 3 but I had a hard time with bug 2.
Your the best and great tutorial by the way!
Do you still create tutorials, do you have a job using Unity?
Cheers,
Patrick Miron
… On Jul 6, 2022, at 7:23 PM, GreenHapi ***@***.***> wrote:
How I Fixed UI bugs
First of all, be sure to use VSync, as otherwise, your game may run at insane FPS, using tons of GPU power and resources. Also, this way you will be able to catch bug number 3.
<https://user-images.githubusercontent.com/9500028/177657571-8f648f42-4641-458f-b85d-c0b39333b8b9.png>
Bugs:
The item icon will disappear when dropping the icon into the original slot or off the inventory grid.
The item icon will stop responding to clicks after the first click and when the mouse stays in the same place (it doesn’t move at all).
The item icon will stop following the mouse cursor when the mouse moves very fast
Bug 1. The item icon will disappear when dropping the icon into the original slot or off the inventory grid.
In InventoryUIController class, OnPointerUp method surround
m_OriginalSlot.DropItem();
with ifstatement
if (closestSlot != m_OriginalSlot) {
m_OriginalSlot.DropItem();
}
Bug 2. The item icon will stop responding to clicks after the first click and when the mouse stays in the same place (it doesn’t move at all).
This one was tricky. I had a bunch of ideas of why that might have been happening and I searched on the internet a lot. I even switched to a new input system, because I thought that the old one might have a bug that prevents clicks from going through if the mouse hasn’t moved.
All my searches were in vain.
Until I fired up Window -> UI Toolkit -> Event Debugger and had seen that the second click goes to GhostIcon if I don’t move the cursor. This was a great clue as to what was happening. Additionally, I used Window -> UI Toolkit -> Debugger with Show Layout mode turned on to visually debug this problem.
<https://user-images.githubusercontent.com/9500028/177657815-e5a7e8a9-726c-4360-94f2-f62105e1c12b.png>
Now was the challenge to pass the second click to the InventorySlot.
This is by no means the best approach for a fix, but it’s the best I currently discovered and it works.
The main culprit is that m_GhostIcon.style.visibility = Visibility.Hidden doesn’t stop GhostIcon from receiving clicks.
In the InventoryUIController class, StartDrag method change
m_GhostIcon.style.visibility = Visibility.Hidden
to m_GhostIcon.style.display = DisplayStyle.Flex;
and in OnPointerUp method change
m_GhostIcon.style.visibility = Visibility.Hidden;
to m_GhostIcon.style.display = DisplayStyle.None;
Then open Inventory.uxml file in UI Builder and change GhostIcon display properties to this settings.
Display to Hidden
Right-click on Visibility and choose Unset.
<https://user-images.githubusercontent.com/9500028/177657826-4de06371-8dc3-4f44-a467-6d23e434d4c4.png>
Save file.
This fixes the bug but introduces a new one. GhostIcon starts to jump all over the place.
The main reason for this is that InventoryUIController can’t get the correct layout.height and layout.width, because of how we hide our GhostIcon with a change of DisplayStyle from Flex to Hidden. Currently, I don’t have a good explanation except that this removes GhostIcon from UI calculations and it needs some time to calculate these values. A time that we don’t wait and so it messes everything up.
Fix for the new bug.
There are two approaches you can take.
Easy fix.
First, one is easy but requires you to set dimensions of GhostIcon manually in InventoryUIController .
You can introduce a variable at the beginning of the class and initialize it with size values of GhostIcon
private static Vector2 m_GhostIconDimensions = new(128f, 128f);
and then use it instead of
m_GhostIcon.layout.height and m_GhostIcon.layout.width
in StartDrag method
//Set the new position
m_GhostIcon.style.top = position.y - m_GhostIconDimensions.y / 2;
m_GhostIcon.style.left = position.x - m_GhostIconDimensions.x / 2;
and in OnPointerMove
m_GhostIcon.style.top = evt.position.y - m_GhostIconDimensions.y / 2;
m_GhostIcon.style.left = evt.position.x - m_GhostIconDimensions.x / 2;
Hard fix.
If you want to initialize m_GhostIconDimensions using code then you have to use IVisualElementScheduler and
IVisualElementScheduler <https://docs.unity3d.com/2022.2/Documentation/ScriptReference/UIElements.IVisualElementScheduler.html>
Create a new method InitGhostIconDimensions in InventoryUIController class
private void InitGhostIconDimensions() {
m_GhostIcon.schedule.Execute(() => {
m_GhostIcon.style.display = DisplayStyle.Flex;
m_GhostIcon.schedule.Execute(() => {
m_GhostIconDimensions = new Vector2(m_GhostIcon.layout.width, m_GhostIcon.layout.height);
Debug.Log(m_GhostIconDimensions);
m_GhostIcon.style.display = DisplayStyle.None;
});
});
}
and call it at the end of an Awake method with
InitGhostIconDimensions();
Note:
for some reason in my original code, it works even this way. I used bold for a code, that was modified.
private void InitGhostIconDimensions() {
m_GhostIcon.schedule.Execute(() => {
m_GhostIcon.schedule.Execute(() => {
**m_GhostIcon.style.display = DisplayStyle.Flex;**
m_GhostIconDimensions = new Vector2(m_GhostIcon.layout.width, m_GhostIcon.layout.height);
Debug.Log(m_GhostIconDimensions);
m_GhostIcon.style.display = DisplayStyle.None;
});
});
}
Bug 3. The item icon will stop following the mouse cursor when the mouse moves very fast
Using UI Toolkit debugging tools I found out that when the cursor moves too fast it leaves the area of the GhostIcon and thus it stops receiving input until you move again into its area.
My ideas for fixing this bug were:
to use Update method to constantly update the position of GhostIcon to be under the cursor even when it can’t receive mouse events because it was “lagging behind”.
The idea was to find a way to keep GhostIco receiving input. Then I thought about creating a container VisualElement for GhostIcon covering the whole UI until the mouse button is unpressed.
Until I accidentally stumbled upon a CapturePointer helper method while digging through Unity Documentation and researching various callbacks for UI elements that maybe could have been helpful for this situation.
Here is a description from the Documentation:
When a VisualElement captures a pointer, all pointer events are sent to the element, regardless of which element is under the pointer.
Unity - Scripting API: UIElements.PointerCaptureHelper.CapturePointer <https://docs.unity3d.com/2022.2/Documentation/ScriptReference/UIElements.PointerCaptureHelper.CapturePointer.html>
That’s exactly what I needed!
In the OnPointerMove method just after the if statement add
m_GhostIcon.CapturePointer(evt.pointerId);
so it looks like this
private void OnPointerMove(PointerMoveEvent evt) {
//Only take action if the player is dragging an item around the screen
if (!m_IsDragging) {
return;
}
**m_GhostIcon.CapturePointer(evt.pointerId);**
...
and in the OnPointerUp method add
m_GhostIcon.ReleasePointer(evt.pointerId)
almost at the end.
**m_GhostIcon.ReleasePointer(evt.pointerId);**
//Clear dragging related visuals and data
m_IsDragging = false;
m_OriginalSlot = null;
m_GhostIcon.style.display = DisplayStyle.None;
}
There are a lot of other bugs to be fixed and improvements that can be made. Although this all may look intimidating at first I didn't know where to even begin to search for how to fix these bugs. It took me on and off about 1.5 days to find all this.
I hope you will build a great game/app and will have fun while you do it! 🥳
—
Reply to this email directly, view it on GitHub <#27 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AHOVI6C355TNZ7K27AJXYGDVSYIONANCNFSM5ZYQBKTQ>.
You are receiving this because you authored the thread.
|
Beta Was this translation helpful? Give feedback.
-
When dropping the icon in the original slot or off the inventory grid, the icon would disappear.
I have fixed this in the code bellow for OnPointerUp() method.
What I can't fix is that after dropping the icon and if I don't move the mouse/pointer, I can't pick up the icon again. If you have a solution to that, I would love to hear from you.
Beta Was this translation helpful? Give feedback.
All reactions