Partager via


Force feedback on GameInput

Use this topic to understand how force feedback on GameInput can manage device output. With force feedback, game input devices can physically move one or more of the device's input controls to provide tactile feedback to the user. Force feedback works with input devices that simulate vehicle operation, such as driving wheels and flight simulation rigs. These devices contain a force feedback motor that applies force to the controller over an axis. On a racing wheel, it's a rotational force that turns the wheel to simulate an in-game scenario. Use force feedback with a flight stick to make levers difficult to push or pull from a particular position.

For more information about the GameInput interfaces that support force feedback, see IGameInputDevice and IGameInputForceFeedbackEffect.

Check for a force feedback motor

To create a force feedback effect, you need the IGameInputDevice interface that represents the input device that you want to apply the effect to. After acquiring the IGameInputDevice interface, check the number of force feedback motors on the device by examining the GameInputDeviceInfo struct. This can be done by calling IGameInputDevice::GetDeviceInfo. If there's a force feedback motor in the input device, the GameInputDeviceInfo member ForceFeedbackMotorCount has a value of one or greater.

Creating a force feedback effect

If a device's GameInputDeviceInfo struct indicates that it has one or more force feedback motors, create a force feedback effect for the device by calling IGameInputDevice::CreateForceFeedbackEffect as shown in the following code.

HRESULT CreateForceFeedbackEffect(  
         uint32_t motorIndex,  
         const GameInputForceFeedbackParams* params,  
         IGameInputForceFeedbackEffect** effect  
) 

The motor index parameter is the index of the motor affected by force feedback. This index corresponds to the appropriate motor in the GameInputDeviceInfo struct's GameInputForceFeedbackMotorInfo array. This array includes information about the force feedback motors that are present and their capabilities.

For the second parameter, build the GameInputForceFeedbackParams struct for the force feedback effect that describes the characteristics of the effect as shown in the following code.

typedef struct GameInputForceFeedbackParams {  
    GameInputForceFeedbackEffectKind kind;  
    union  
    {  
        GameInputForceFeedbackConstantParams constant;  
        GameInputForceFeedbackRampParams ramp;  
        GameInputForceFeedbackPeriodicParams sineWave;  
        GameInputForceFeedbackPeriodicParams squareWave;  
        GameInputForceFeedbackPeriodicParams triangleWave;  
        GameInputForceFeedbackPeriodicParams sawtoothUpWave;  
        GameInputForceFeedbackPeriodicParams sawtoothDownWave;  
        GameInputForceFeedbackConditionParams spring;  
        GameInputForceFeedbackConditionParams friction;  
        GameInputForceFeedbackConditionParams damper;  
        GameInputForceFeedbackConditionParams inertia;  
    };  
} 

Choose a GameInputForceFeedbackEffectKind enum, and then initialize the corresponding GameInputForceFeedbackParams struct.

For example, to create a feedback effect with the spring behavior, GameInputForceFeedbackParams consists of the GameInputForceFeedbackEffectKind value GameInputForceFeedbackSpring and the GameInputForceFeedbackConditionParams struct for a spring. Fill in the parameters for your chosen GameInputForceFeedbackEffectKind enum.

After selecting the force feedback motor effect by its index and creating the GameInputForceFeedbackParams struct, call IGameInputDevice::CreateForceFeedbackEffect to create the effect. It's represented by an IGameInputForceFeedbackEffect interface.

The force feedback effect's lifetime is associated with the created IGameInputForceFeedbackEffect interface. When the effect is created, it's loaded to the device. When the last reference is released, the force feedback effect is stopped and unloaded from the device motor.

Applying and updating force feedback effects

When a force feedback effect is created, it's loaded directly into the device motor. A force feedback motor has a finite amount of memory. This limits the number of force feedback effects that are loaded and played at the same time. Calling IGameInputDevice::CreateForceFeedbackEffect after reaching this limit causes the function to return an error.

After creating a force feedback effect, it's loaded to the force feedback motor in a stopped state. After it's loaded, use the IGameInputForceFeedbackEffect interface to set the state of the effect to Running. This plays the effect on the device motor.

States of force feedback effect

A force feedback effect moves through several states to match the current state of the game. It's important that you update and take note of the state of an effect in accordance with your game to maintain the expected behavior.

The states of force feedback can be set according to GameInputFeedbackEffectState as shown in the following code.

typedef enum GameInputFeedbackEffectState    
{  
    GameInputFeedbackStopped = 0,  
    GameInputFeedbackRunning = 1,  
    GameInputFeedbackPaused = 2  
} GameInputFeedbackEffectState  

After the force feedback effect is created, it changes to the Stopped state. If a new or stopped feedback effect is set to the Running state, it plays from the beginning of the effect. Setting the state to Paused causes the force feedback effect to stop affecting the motor. However, setting a Paused state effect to Running causes the force feedback effect to apply the effect pattern where it left off.

Stopping an effect ends the effect, but you can trigger the effect again later. For example, when a user leaves rough terrain in a racing game. Likewise, pausing an effect is useful for situations where gameplay is unchanged but the user wants to navigate the UI, such as a pause menu.

Set the state of a force feedback effect by calling IGameInputForceFeedbackEffect::SetState.

Updating a force feedback effect

Adjust the gain of a force feedback effect or provide a new set of parameters if the new GameInputForceFeedbackParams struct shares the same GameInputForceFeedbackEffectKind enum.

Gain

Change the intensity of a force feedback effect by adjusting its gain with the IGameInputForceFeedbackEffect::SetGain function as shown in the following code.

void SetGain(  
         float gain  
)  

The gain can be a value between 0 and 1. By default, the gain of a force feedback effect is set to 1. This function is primarily used to ease the intensity of an effect.

Setting new parameters

Provide new parameters for a force feedback effect by using the IGameInputForceFeedbackEffect::SetParams function as shown in the following code.

bool SetParams(  
         const GameInputForceFeedbackParams* params  
)  

When using this function to replace the parameters of a force feedback effect, use the same GameInputForceFeedbackEffectKind enum as the force feedback effect you're setting parameters for. New parameters take immediately, and they're applied without stopping the running effect. Note that the duration timer is not refreshed if the duration value does not change. It will only be refreshed if a different duration value is provided, or the effect is stopped and restarted.

If the running effect is stopped, it's restarted with new parameters. Some games can change parameters to simulate different feedback patterns by setting the parameters for a feedback effect with a GameInputForceFeedbackEffectKind enum of GameInputForceFeedbackConstant.

Capability differences between GIP and HID devices

On console, all devices use the GIP driver model. On PC, devices can use either the GIP or HID driver model; installing vendor drivers generally converts them to HID mode (unless there is a physical switch for manual control). Force feedback capabilities of HID devices are limited by the DirectInput API for which they were originally designed. GameInput makes a best effort to work around these limitations where possible. Nevertheless, some differences remain.

HID devices currently restrict force feedback to the AngularX axis regardless of additional axes supported by the hardware. This configuration provides good support for the vast majority of racing wheels.

HID force feedback is currently available in 19H2+ versions of Windows and will be updated to work in 19H1 in a future update.

See also

IGameInputForceFeedbackEffect

IGameInputDevice