How to select a static mesh with a controller?

Hi,
I am looking for a way to make static mesh buttons selectable with a controller. As if they were UI buttons but in 3D. Is there a way to make them focussable?



To clarify. We have a gamepad and use directional arrows / joystick to navigate a grid made out of static meshes? Once navigated to, the element produces some kind of feedback / highlight indicating that it’s currently selected.

I see a cursor there. Do we hop from a tile to tile or the cursor moves slowly until the next tile is underneath it?

Am I getting it right?

The default controls are with mouse and keyboard, but I would like to add full gamepad support.

When using the gamepad, the player just hops from tile to tile between the buttons. The cursor is not moved by the gamepad, even though I would consider that solution if it’s easier to implement than making the button meshes selectable/focussable.

Maybe I have to add an invisible widget overlay instead of trying to focus the 3D meshes?

Both can be done.

  • move the cursor and convert screen coords to world and trace along that vector until you hit, or simply get hit under cursor
  • to skip from tile to tile with no cursor:
    • trace in the direction of the joystick / arrow
    • if hit, remove previous highlight, show new highlight

There is also a third solution: have each static mesh pop up an invisible UI widget component and use a widget interaction component. Sounds awkward, though and probably an overkill.


One way or another, consider encapsulating the highlighting logic inside the Static Mesh Component itself. It will dramatically simplify management and make it more modular in case you needed more of those buttons elsewhere. If those buttons require complex interactions or will become complex in a hierarchical sense, consider using actors instead. Because this…

image

…is not sustainable / manageable in the long run. Unless you really need a one-off only and never ever reuse it anywhere else.


And yet another way:

  • associate the static meshes components with integers in a map container
  • use modulo to move across rows / columns

That should be the most efficient, scalable and easy to maintain, especially if you inject the highlight logic into the SMC.

2 Likes

Thank you @Everynone for your solutions.

This 6-button-set is a one-off only and never reused anywhere else. Also the highlight effect is only activated OnClicked. So I think that the 3rd solution would actually work best in this situation (consideruing that I have no clue on how to make the cursor moveable with a joystick or how to trace in the direction of the joystick).

Can you please give me a hint on how you would make the invisible UI widget popup and use a widget interaction component?

The widget approach would be the most complex one and somewhat finicky to set up. You’d also need to learn about widget navigation on top of that. And widget interaction component is tracing at the same time and requires extra steps. I can only recommend it if there’s no other way to achieve what you want. As in, you’re using an obscure VR controller device and need a workaround.

  • consider the modulo approach, it’s pretty much just math
  • tracing has so many applications so you’ll need to learn in anyway…

a hint on how you would make the invisible UI widget popup and use a widget interaction component?

probably an overkill

  • override the SMC and have it dynamically add an invisible widget component in world space overlaying the facing side
  • bind an onMouseEnter and have the dispatcher report to the actor owning the SMCs
  • the actor manages the highlights / behaviour
  • use input to move / orient the Widget Interaction Component so it can hit specific tiles

Were you to go this route, you’d still need to do the modulo math (or widget navigation) and tracing and the same time. I eventually converted this to work with a gamepad (and mouse, and VR). It works fine but it’s a lot of work.

Okay, that does sound too much, I’m not going VR with this. I’ll try to learn what a map container is and how to use modulo then.

Thank you for clearing this up and for your time.

If you need something super straighforward and can get away with hard-coding values:

  • add meshes to an array:

  • navigation (use gamepad input)

You get:

The tiles are ordered 0-5 since they sit in an array.

  • input right → add 1 to index
  • input left → remove 1 from index
  • input up → remove 3 from index (switch to previous row)
  • input down → add 3 to index (switch to next row)

Clamps ensure we do not exceed array bounds.

That is so neat and exactly what I try to achieve. :smiley:

The meshes are already in an array like so:

How do I get to the first SelectedIndex though?

For example: the player has button “Switch” selected and pushes GamepadThumbstickRight to get to the first tile (with the flash icon) to select it.

The navigation of button “Switch” is set to Right > Escape but will not go over to the flash tile.

I am confused. You said you wanted to highlight meshes as if there were widgets but it seems that you are actually using widgets (as well)…

If so, I’d rely purely on widget navigation and dispatch to the associated mesh. No need to faff around with indexes whatsoever

I’m sorry to have posed my question incorrectly. Thank you, I’m grateful for all your help.

In case you need help, could you give us a hint regarding how the meshes and the widgets make it into the game?

  • do you place an actor in the level or is it spawned somehow?
  • which actor creates the widgets?

I am assuming that you can already navigate the widgets with the controller, it’s a matter of the widget telling a specific mesh what to do. Am I close?

Yes, you’re absolutely right.

The Button Actor is spawned into the level by the main Widget.

Well, more precisely the ButtonSpawner is placed into the level, which then spawns the appropriate set of mesh buttons. These can be switched out for other sets of mesh buttons that contain different songs.

Navigating the other widget buttons already works, so I am assuming I need to put 6 invisible boxes in the main widget and make Event Dispatchers that activate the mesh buttons?

No need for extra boxes, bind the dispatcher directly to a custom event inside the actor the widget spawned. I can’t recall from the top of my head which event fires when a button / widget is navigated to. And can’t tell from the setup whether you’re using native buttons or user widgets.

The main widget setup looks like this:

I was thinking to place 6 invisible buttons on the position where the mesh buttons are and then bind events to them?