Migrating from v1
v2 is a rewrite, not an update. The ideas are the same (lightbar, rumble, trigger effects), but where they live and how you call them changed:
| v1 (1.x) | v2 | |
|---|---|---|
| Input | RawInput plugin + an INI block | Native input device, nothing to configure |
| Output API | DualSenseControllerManager component on an actor | Static DS nodes, a Game Instance Subsystem in C++ |
| Sending output | The whole state every frame | Only what you change, when you change it |
| Controllers | One | Up to 4, with reconnection |
| Trigger effects | 3 (plus Calibrate), float parameters cut to whole numbers | 12 plus Raw, zones 0–9 and strengths 1–8 |
| Rumble scale | 0–10, about 4% of the motor at most | 0–1, the full motor |
| Engines | 5.1 to 5.7 | 5.7 and 5.8 |
Checklist
Back up the project
Commit or copy the project first. Note where the v1 nodes are used: search for DualSenseControllerManager in the Content Browser (Reference Viewer) or for Update Dual Sense Controller with Find in Blueprints.
Replace the plugin
Close the editor, delete Plugins/DualSenseUnrealEnginePlugin and copy the v2 package in its place. See Installation.
Remove RawInput
v2 reads the controller itself. Remove the DualSense +DeviceConfigurations=(VendorID="0x054C",...) lines from [/Script/RawInput.RawInputSettings] in Config/DefaultInput.ini, and disable the Raw Input plugin if nothing else uses it. If you skip this, every button fires twice.
Remap the extra buttons
Most buttons were already standard gamepad keys in v1 and keep working. The ones that used GenericUSBController_* keys need new keys in your Input Mapping Contexts (or InputKey events):
| v1 RawInput key | DualSense button | v2 key |
|---|---|---|
GenericUSBController_Button9 | Create | Gamepad Special Left |
GenericUSBController_Button10 | Options | Gamepad Special Right |
GenericUSBController_Button13 | PS | DualSense PS Button |
GenericUSBController_Button14 | Touchpad click | DualSense Touchpad Click |
| (not available) | Mute | DualSense Mic Button |
Remove the component
Delete the DualSenseControllerManager component from your actors. Its Initialize and Free calls go away: v2 opens and closes the controllers on its own.
Replace the nodes
Use the tables below. Most of the time a v1 Update Dual Sense Controller becomes a few DS Set ... nodes followed by DS Update Output.
Move the logic off Tick
v1 needed the state sent every frame. In v2 the state persists: set it when something happens (weapon equipped, damage taken) and remove the Tick logic.
Retune on the controller
Rumble now uses a 0–1 scale that reaches the full motor, and Section Resistance now applies its force. Feel every effect again with a controller in hand.
Node by node
| v1 (DualSenseControllerManager) | v2 |
|---|---|
| Add the component to an actor | Nothing: the DS nodes work from any Blueprint |
| Initialize Dual Sense Controller | Not needed. Check with DS Is Controller Connected if you need to know. |
| Free Dual Sense Controller | Not needed. |
Update Dual Sense Controller (FDS5OutputState) | DS Set Full Output State + DS Update Output, or individual DS Set ... nodes + DS Update Output |
| Update Lightbar Color | DS Set Lightbar Color + DS Update Output. It no longer resets the triggers and rumble. |
| Make Continuous Resistance (start, force) | DS Make Trigger Continuous Resistance (Legacy) for the same bytes, or DS Make Trigger Feedback |
| Make Section Resistance (start, end, force) | DS Make Trigger Section Resistance (Legacy), or DS Make Trigger Weapon / DS Make Trigger Slope Feedback |
| Make Effect Ex | Make FDS5TriggerEffect with Effect Type = Effect Ex (Legacy, Deprecated), or better DS Make Trigger Vibration / DS Make Trigger Machine |
Trigger effect in leftTriggerEffect / rightTriggerEffect | DS Set Trigger Effect with Hand = Left / Right / Both |
leftRumble / rightRumble (0–10) | DS Set Rumble (0–1), or Unreal's Play Force Feedback |
playerLeds | DS Set Player LEDs (presets) or DS Set Player LEDs (Bitmask) |
microphoneLed | DS Set Mic LED |
Before and after
The same "weapon trigger and lightbar" logic in v1 and in v2:
Types
| v1 | v2 |
|---|---|
FTriggerEffect | FDS5TriggerEffect. Float fields are now int32; the v1 fields map to LegacyStartPosition, LegacyEndPosition, LegacyForce, bKeepEffect, BeginForce, MiddleForce, EndForce. |
ETriggerEffectType::NoResitance | Off |
ETriggerEffectType::ContinuousResitance | ContinuousResistance |
ETriggerEffectType::SectionResitance | SectionResistance |
ETriggerEffectType::EffectEx | EffectEx (deprecated) |
ETriggerEffectType::Calibrate | Removed |
FDS5OutputState fields (leftRumble, lightbar, leftTriggerEffect...) | Same struct, PascalCase fields (LeftRumble, Lightbar, LeftTrigger...), rumble now 0–1 |
FPlayerLeds (bitmask, playerLedFade, brightness) | Bitmask, bPlayerLedFade, Brightness |
ELedBrightness::LOW / MEDIUM / HIGH | Low / Medium / High |
FTouch, FBattery | FDSTouch, FDSBattery |
FDSColor | Removed, use FLinearColor |
What feels different
- Rumble. v1 wrote the 0–10 value straight into the motor byte (0–255), so the strongest v1 rumble was about 4% of the motor. v2 maps 0–1 to the full range, so the old maximum is about
0.04in v2. Expect to raise your values. - Section Resistance. v1 never applied the force of this effect. In v2 the legacy node applies it, so it is much stronger with the same numbers.
- Trigger parameters. v1 took floats but cut them to whole numbers from 0 to 255, so values like
0.5became0. v2 uses whole zones and strengths from the start. - Lightbar. Update Lightbar Color in v1 reset everything else to zero. In v2 each part of the state is independent.
Staying on v1
v1 keeps working on Unreal Engine 5.1 to 5.7 and its packages stay on Gumroad. Its documentation is under v1.3.