Repository navigation
Replies: 3 comments
|
I quite like |
|
A few more refinements based on my latest research: Currently Bevy provides the
Note that not all of these questions require actually looking inside the Unfortunately, the An input mapper library can work around all this by defining its own set of "vendor neutral" components, which are synchronized from |
|
Another addendum: Rumble should be a component. Currently you control rumble by posting an event, but a level-based API would be more convenient for game developers. Having a |
Uh oh!
There was an error while loading. Please reload this page.
Recently, a question was asked on Discord about integrating a Bevy input mapper with SteamInput. As a consequence, I have been thinking a lot about how this would work.
Note that, until about a month ago, I knew nothing about Steamworks, so what I say may be wrong - feel free to call out any mistakes I make!
Steam is arguably the dominant platform for game distribution, so I think supporting it is pretty important. At the same time, we obviously don't want Bevy to depend on Steam. But I think that there are things we can do to improve the integration story generally that don't requires a direct dependency on Steamworks.
(BTW, I have looked at both
bevy_steamworksandsteamworkscrates.)SteamInput manages inputs from game controllers. As such, it directly competes with
gilrs, which is the crate that Bevy currently uses for reading gamepad input.SteamInput has its own input mapping strategy, which is accessible via the Steam game overlay. This means that an input mapper such as LWIM or BEI would need to process events coming from Steam as post-mapped rather than pre-mapped. Thus, the events you get from Steam are not button presses but high-level actions like "Thrust" or "Fire".
A Bevy input mapper can easily process these events through its own input contexts, as long as the action ids match. This requires that the input mapper have some means of labeling actions using a stable identifier that can be recorded in the Steam config file (
.vdf).Steam only allows one action map to be active at a time, but you can stack additional "layers" on top of the map. This is different from the strategy used by BEI, where you can have any number of input contexts be active, organized by priority. This isn't a problem, however, because there's no requirement that there be a 1:1 correspondence between steam's action maps and input contexts. The simplest approach is to make a single large action map that contains every action in the game; the only downside to this is that it mean's you can't have mappings that vary by context. There are other ways to organize this, but it requires some thought.
There are a few things that we lose going through Steam, but they are relatively minor. One is class-based bindings: the ability to bind an action to "any button". With Steam, you only get actions that have been mapped to specific buttons.
Also, if your input mapper has a "hold to charge" or "double tap" feature, you no longer have access to the internal timers (which you might use if you want to display a "charging" effect). Instead, you'll have to do these calculations in your simulation instead of at the input mapper level.
If you have both
SteamInputandgilrsactive, you'll receive double events: pressing theAbutton will be received on both channels. Worse, the source id for these events is different, and there's no way to correlate them: you can't know for sure that the button press that you got throughgilrsis coming from a different device than the one you got viaSteamInput. About the best we can do, I think, is just disablegilrssupport when running in aSteamInputenvironment.Let's talk about gamepad branding: both
gilrsandSteamInputsupport a variety of controller brands (XBox, Playstation, Switch, and Generic). When displaying prompts ("Press A to continue"), we need to know the brand so that we can display the correct text and artwork. BothgilrsandSteamInputprovide support for determining the gamepad brand, but the mechanisms are different.Fortunately, we can abstract this. Bevy creates an entity for each
gilrsgamepad, which stores the device id for the pad. We can do the same thing withSteamInput, storing theInputHandle_tas a component on an entity. We can then use these entities polymorphically: game code does not need to know whether the entity represents agilrsgamepad or aSteamInputgamepad. They will of course generate different events, but that should be handled by the mapper. For all other purposes - device filtering, player assignment, and brand queries, we can use the entity directly.Once we have an entity-per-device, we can simply store the brand as a component on the entity.
All reactions