Game Controller Customization and Button Icon Display

I am experimenting with how my game behaves in iOS 14 beta 6 with the new game controller customization feature. I'm on an iPhone 6s using a Horipad Ultimate controller and I have my controller customized as follows:

A Button (selected X)
R1 Button (selected A)
All other buttons are unselected (i.e. default, mapped to themselves)

In code, I log when a button is pressed:
Code Block
if ([extendedGamepad buttonA].isPressed) {
NSLog(@"Button A pressed");
}
if ([extendedGamepad buttonX].isPressed) {
NSLog(@"Button X pressed");
}
if ([extendedGamepad rightShoulder].isPressed) {
NSLog(@"Button R1 pressed");
}

Also, for each of these buttons I print what their current sfSymbolsName value is:
Code Block
NSLog(@"Button A symbol %@", [[extendedGamepad buttonA] sfSymbolsName]);
NSLog(@"Button X symbol %@", [[extendedGamepad buttonX] sfSymbolsName]);
NSLog(@"Button R1 symbol %@", [[extendedGamepad rightShoulder] sfSymbolsName]);

When I run my game, I see the following results:
  • Press physical button A on attached game controller: Game prints "Button X pressed"

  • Press physical button X on attached game controller: Game prints "Button X pressed"

  • Press physical button R1 on attached game controller: Game prints "Button A pressed"

This is more or less what I expect. However, with the same setup, the results of the sfSymbolsName prints are as follows:
  • "Button A symbol x.circle"

  • "Button X symbol x.circle"

  • "Button R1 symbol a.circle"

This seems to be a reverse of the way buttons are responding to presses, though I can see how it makes sense, since several game controller buttons can be remapped to the same button simultaneously, and sfSymbolsName can only report one value.

But my question is, what's the proper way to figure out how a button is mapped so that I can display the correct button icon on screen?

In the scenario above, let's say my game expects to use the A button on the controller to have the character jump. In my code, I would check "[extendedGamepad buttonA].isPressed" and if it's true, assume the A button is pressed and do my jumping action. As the controls are mapped in my above example, pressing the physical A button on the controller would not cause a jump, nor would pressing the physical X button, but pressing the physical R1 button would cause a jump.

But I want to indicate to the user which button they should press to jump. On the one hand, I could assume the user knows how they remapped buttons and just always say "Press a.circle to jump". That seems a little unfriendly. The game should be able to tell that pressing R1 will actually cause the jump, so I should be able to say "Press r1.rectangle.roundedbottom to jump". The player sees the R1 symbol on the screen and knows to press the physical R1 button on their controller, and because of the mapping, when my code checks if the A button is pressed, it returns true.

But how do I determine that from the values I'm presented with? In code, the A button's sfSymbolsName tells me x.circle, which is not what I want. I'd have to scan through all the buttons in the extended gamepad object and find that the R1 button's sfSymbolsName returns a.circle, which could tell me that it's mapped to the A button. But then nothing actually returns the name I want, r1.rectangle.roundedbottom, so I have to have my own mapping to know that the R1 button uses that symbol name.

Is this the right way to do this? Is there another way I'm missing to have my game be able to show the symbol on screen that matches the physical button that's mapped for that control?

I looked at the other values on the button object, localizedName and aliases, and neither seem to help. localizedName returns the same as sfSymbolsName, and aliases returns names for the current button (in my scenario above, [buttonA aliases] returns "Button A", not the X button or the R1 button).

Thanks for any help you can provide!
I have come accross the exact problem you are describing.

If I remap A to B, and nothing else.
So pressing A sets "extendedGamepad.buttonB.pressed" to 1.0

I can detect when the B button is pressed.
But the B button retuns the icon for the B button.
I need to show the user the A button icon.

We wrote a function that takes in the sfSymbolsName and tries to reverse engineer the button that symbol will normally correspond to. This usually works, as long as all the buttons are mapped.

However because (in my example) button A has no mapping to activate it our function fails.

But this seems the only way to work out the button mappings.



Yes, this is also the solution we ended up with. We had to do a reverse lookup to determine which button to display. That being said, we tested this out with the released versions of iOS and tvOS (as of this writing, iOS 14.0.1 and tvOS 14.0.2), and they fixed the problem in iOS but not in tvOS. So we can actually just use the reported sfSymbolsName on iOS, but on tvOS we still have to perform the reverse lookup.
It appears as of tvOS 14.2 that sfSymbolsName is finally behaving properly, so I've updated my code again to do the reverse lookup for tvOS 14.0 - 14.1 and act normally for iOS 14 and tvOS 14.2+.
Game Controller Customization and Button Icon Display
 
 
Q