#Filtering UI clicks

1 messages · Page 1 of 1 (latest)

compact river
#

Hello everyone. If I have UI, I need somehow to filter the clicks, when they were over UI element, or when they were over some other object. So what are my options if I want to do this?
I am doing this in a job and I have an idea of doing it by using a ComponentLookup.HasComponent, so I just check if the raycasted entity has some tag, which UI cannot contain. But this way seems to me not so effective (because of using ComponentLookup) and not so flexible, as it could be.
So maybe I don't see something and there is another way of filtering

crystal swift
compact river
#

The thing is to stop something which is called OnClick of some object (not UI), when we click UI.
So for example if I click on some button I do not want my unit behind that button to be selected

crystal swift
#

don't use callbacks at all

compact river
#

And I want my SelectionSystem to be BurstCompiled, so I cannot check MyButton.IsClicked there, because it is a managedComponent

crystal swift
#

can all your buttons be hardcoded as fields?

#

or you need a generic version?

compact river
#

What do you mean by "hardocoded as fields"? To copy the bool value of IsPressedThisFrame in some unmanaged data component?

crystal swift
#

by hardcoded as fields I mean, can you make it so all your buttons are stored in just one type?

#

for example

#

struct MyGameplayUI { public Button pauseButton; public Button menuButton; }

compact river
#

Button is a class, how can I put it in the unmanaged component?

crystal swift
#

public struct Button { public bool isClicked; }

compact river
#

Well, okey, let's suppose I put all my buttons, sliders or another interactive components in such struct. But then 2 questions:

  1. How can I track clicks on some non interactive UI things? For example some panels, where the buttons are fitted? Creating additional fields in the struct for them as well?
  2. How to fill this fields, if we should not use events like OnClick or smth like that? Moreover non-interactive panels do not have even such thing, so how to track a click on them?
crystal swift
#

you can use OnClick events, no problem with that

#

it's just that you write values to your temporary data structure

#

and then read it from system's OnUpdate

cinder quarry
crystal swift
#

basically, goal is: make it so your UI input is as simple as Input API (old input system)

#

just like Input.GetKeyDown(KeyCode.R)

#

for example MyUIInput.IsPauseButtonPressed()

#

and simply store it in some singleton struct

#

then you can even skip scheduling jobs if relevant button is not pressed

#

by early returning in other system updates

#

you literally just can do same with UI input

#

where instead of _controls you'll have your UI manager reference

compact river
crystal swift
compact river
#

Won't it create some stalls, when monobehaviour is trying to modify that struct?

compact river
#

where all data about clicks on UI is stored and which is read by my system

crystal swift
#

and then system simply copies it to entity data

compact river
#

oh, I got it

crystal swift
#

that system must run as soon as possible

#

before any jobs are scheduled

#

so it won't do any syncs

#

that would make your input overhead is nearly 0

#

allthough.. makes no difference when it runs

#

your input will be stored on singleton which is only read by main thread (systems)

#

while passed to jobs as copy

compact river
#

The only moment I am still not sure is the next one:
For example I have a SelectingUnitSystem which works on a single leftButton click. So every I click, I will have to check ALL bool-s of UI data (to check that no button, slider, or non-interactible panel was clicked). And the same I will have to do simultaneously before all commands, that work on the leftButton. I don't think there will be a lot of them, but still it doesn't look like an accurate solution. Because if I add any UI component, I will have to add it to many places in code, which doesn't look very convinient..
Also I still don't understand a little, how can I track if non-interactible panel (which doesn't have an event OnClick) was clicked...

crystal swift
compact river
#

Well, to understand if it was clicked on the UI and if so, I will not schedule the Job for selecting unit

crystal swift
#

ah, you mean this

#

why not just have additional field bool cursorOverUI

#

and each time cursor is over it

#

just set it

#

and then you only need to check leftClick && !cursorOverUI

compact river
#

So can I fill that field by just getting a EventSystem.current.IsPointerOverGameObject() value each frame? Or it will be too heavy for every-frame operation?

crystal swift
#

I personally never used ugui, and that method never worked for me in UI Toolkit 😅

compact river
#

I didn't understand a little

crystal swift
#

if you want to optimize it - you can always do additional checks later

#

for starting - don't think you'll be able to even find it in profiler

compact river
#

because it will be too fast and I will not notice it?