SetValue & Select methods being called multiple times with mouseover and clicks

altug

New member
While debugging I realized this on my project. As I see its triggered from both two lines in ActionButton.cs.
Line 207 and line 211:
1735830636763.png

Not happening with onClick selections, its just mouseover selections.
I thought its a flaw in my UI hierarchy design, but I also tested with the demo scene and its same.
I'm using a custom AttributeViewModule which does some quite work so its not good to be done twice.


Edit: Temporarily I fixed it with this in my inherited ItemViewSlot;

C#:
public override void OnSelect(BaseEventData eventData)
{
    var eventSystem = EventSystemManager.GetEventSystemFor(gameObject);
    if (!eventSystem.alreadySelecting) return;
    base.OnSelect(eventData);
}
 
Last edited:
@Sangemdoko is on vacation and will respond next week when he gets back but I think you should be able to change the alreadySelecting block to:

Code:
if (!eventSystem.alreadySelecting && eventSystem.currentSelectedGameObject != gameObject) {
 
Happy new year!

I'm sorry for the delay I was on Holiday.

Oh perhaps base.OnPointerEnter(eventData) already selects the Selectable alling OnSelect(eventData) so I'm doing it twice? I'll note this down to double check when I get some time :)
 
Hi @Sangemdoko, I'm testing this issue a bit more after finding out this is happening also with click selections and for other classes with SetValue and Select methods. I tested with empty project with demo scene with 1 wooden sword in inventory.

Below I did only move default wooden sword to another slot. And those are the calls, as I see its more than 40.

1736262270629.png

and this is just a mouseover:

1736262611328.png
 
I made two changes in Action button

Code:
/// <summary>
/// Invoke OnSelect even if it was already selected.
/// </summary>
public override void Select()
{
    var eventSystem = EventSystemManager.GetEventSystemFor(gameObject);
    if (eventSystem.alreadySelecting || eventSystem.currentSelectedGameObject == gameObject) {
        OnSelect(null);
    } else {
        eventSystem.SetSelectedGameObject(gameObject);
    }
}

and

Code:
/// <summary>
/// Call the On Pointer enter event.
/// </summary>
/// <param name="eventData">The event data.</param>
public override void OnPointerEnter(PointerEventData eventData)
{
    if (!m_SelectOnPointerEnter || !eventData.IsPointerMoving()) {
        base.OnPointerEnter(eventData);
        return;
    }
    var eventSystem = EventSystemManager.GetEventSystemFor(gameObject);
    if (!eventSystem.alreadySelecting) {
        eventSystem.SetSelectedGameObject(gameObject);
    } else {
        OnSelect(eventData);
    }
    OnPointerEnterE?.Invoke(eventData);
}

To me it prevents the double selection of the ActionButtons.

I hope that helps
 
Hi Sangemdoko, thank you, will test it as soon as I can.
The same behaviour happens with AttributeViewModule also. I have double triggered SetValues from them.


First one's path:
1736790673682.png

second one:
1736790695844.png
 
Last edited:
1737130464515.png

This is from a single ItemPickup object when it appears in the scene. I was planning to create my own item visualizer to display my procedural stats; I have to access my custom attribute to get stats data, but this situation makes me think as ItemVisualizer will try to get the data 4 times minimum and will spawn my custom stat display object the same amount.. I'm really happy with the asset and customizing it to my needs without any issue, but this multiple called methods over and over seems almost everywhere :(
 
Hi altug,

I investigated these and I'm afraid that there are good reason these function get called multiple times to avoid edge cases. Most of these came from bug reports, and the fixes required calling the the function at other times. In some cases (especially on initialization) it may cause visuals to be drawn multiple cases in certain instances.

In your first inquiry about AttributeModule. This gets called from the Description binding component. It gets called twics because it gets called on enable (in case the inventory was updated in between enabled/disable which is optional) and it also gets updated on select (which is optional).
Having out system have many options also means it needs to work as expected in all possible scenarios, sometimes at the cost of calling functions multiple times in certain use cases.

For the second inquiry about pickups. It's a similar issue. It gets called multiple times to avoid bugs in certain edge cases.

In the case of pickups it's 4 times because it does the following

1. On enable it cleanup the view in case it was previously pooled or to return it to the pool in a reset mode if the ItemView prefab instance need to change.
2. Then it draws the current item visual

Then optionally the ItemObject bound refreshes on start or the bound item changes, this causes the item to redraw again. Which repeatsthe first two steps.


I guess in this specific case if ItemObject bound the item before the ItemVisual enable function happend then it would only call it twice instead of 4 times. which is an improvement.

Perhaps if you were to change the Execution Order of those scripts it would reduce the number of times it is updated.

I hope you understand why these multi calls happen.

If you want you can optimize it specifically for your game if you know for sure that certain things you happen in a different order. You are free to change the source code to fit your needs :)

Best of luck and thank you for bringing this to my attention
 
Back
Top