-
Notifications
You must be signed in to change notification settings - Fork 12
Example Project: Gyroscope Aiming
To explore the full implementation and see all these features working together, you can download the complete Unreal Engine project.
Welcome to the Gyroscope Aiming tutorial for the Windows Dualsense Unreal Plugin. This guide will walk you through implementing a precise and responsive motion-based aiming system, a feature that can significantly enhance player immersion and control in shooter games.
Using the Arena Shooter UE 5.6 template as our foundation, we will build a complete Aim Down Sights (ADS) Gyro Aiming feature from the ground up. In this example, the gyro aiming will seamlessly activate whenever the player holds the L2 trigger to aim down sights, providing intuitive and accurate fine-tuning control.
Our first and most critical step will be tackling the calibration process. You will learn how to use an example UMG widget to create a user-friendly calibration interface, ensuring a stable and drift-free aiming experience right from the start.
⚠️ Important Note: Proper calibration is the key to high-quality gyro aiming. This tutorial emphasizes this initial step as it is essential for eliminating sensor drift and establishing a perfect "neutral" position for the controller.
🏆 By the end of this guide, you will have a practical, gameplay-ready implementation and a solid understanding of how to:
- ✅ Create a calibration widget to initialize the controller's motion sensors correctly.
- ✅ Activate and deactivate gyro aiming dynamically using the L2 trigger for ADS.
- ✅ Translate gyroscope data into smooth and accurate camera movement.
To ensure a clean and focused start, we've created a dedicated environment specifically for the calibration process. This isolates the calibration logic from the main gameplay, making it easier to manage and trigger only when needed (for example, the first time the player starts the game).
All the necessary assets for this tutorial can be found in the following project directory:
Variant_Shooter
Here are the key components we've set up:
-
Dedicated Calibration Level 🗺️ A new level has been created to host the calibration widget and logic. This is the first level the player will see, ensuring the controller is calibrated before they jump into the action.
-
Asset:
Level_Calibration
-
Asset:
-
Specialized Player Controller 🕹️ This level uses its own Player Controller, which is responsible for creating and displaying the calibration widget on screen as soon as the game begins.
-
Asset:
BP_CalibrationShooterController
-
Asset:
-
Calibration UI Widget 🖥️ An intuitive and straightforward UMG widget has been designed to guide the player through the calibration steps. This widget will provide instructions and visual feedback on the process.
-
Asset:
UI_Calibration/BP_CalibrationWidget
-
Asset:
The core logic for the calibration process resides in our dedicated player controller, BP_CalibrationShooterController. Instead of running automatically, we give control to the player, ensuring they can start the calibration when the controller is ready and resting on a stable surface.
The sequence is triggered by a player input—in our example, we use the "Confirm" button (the X button on the DualSense). This logic is handled within the Event Graph of BP_CalibrationShooterController.

Here is a breakdown of the Blueprint nodes connected to the Input Action event:
-
Enable Gyroscope Values- This is the first essential step. This node "wakes up" the controller's motion sensors, allowing the plugin to start receiving accelerometer and gyroscope data.
- The
Enable Gyroscopecheckbox must be tickedtrue.
-
Start Motion Sensor Calibration- This function begins the calibration process itself. The plugin will read the sensor data for a set duration to determine the controller's resting state, creating a stable "zero point" to prevent aim drifting.
-
Calibration Duration (Seconds): Defines how long the calibration will run. A value between 2-3 seconds is usually sufficient. -
Noise Deadzone Percentage: This sets a threshold to ignore minor, unintentional movements or sensor noise after calibration, resulting in a smoother aiming experience.
-
Set Start Calibration- This is a custom boolean variable we create. Setting it to
truehere helps us signal to our UMG widget (BP_CalibrationWidget) that the calibration process has officially begun, so it can update its display accordingly (e.g., show a progress bar or "Calibrating..." text).
- This is a custom boolean variable we create. Setting it to
With this setup, the player is in full control, ensuring a much more reliable and accurate calibration.
Once the calibration is initiated by the player, we need to monitor its progress and provide visual feedback. This is handled within the Event Tick of our BP_CalibrationShooterController. The logic continuously checks the status and updates the UI widget accordingly.

Here’s how the logic on Event Tick works:
-
Check if Calibration is Active
- The first
Branchnode checks our custom boolean variable,Start Calibration. This ensures that we only run the monitoring logic after the player has pressed the button to begin.
- The first
-
Get Motion Sensor Calibration Status- This is the key function from our plugin for monitoring the process. It polls the controller and returns two important values:
-
Progress: A float value from0.0to1.0representing the percentage of the calibration's completion. -
Return Value: A boolean that istruewhile the calibration is still running and becomesfalseonce it is finished.
-
- This is the key function from our plugin for monitoring the process. It polls the controller and returns two important values:
-
Update the UI Widget 🖥️
- The
Progressvalue is fed into a variable within ourBP_CalibrationWidget(here namedCalibration Percentage). This variable can be used to drive a Progress Bar or a text field in the UI, giving the player real-time feedback.
- The
-
Check for Completion ✅
- The second
Branchnode checks theReturn Value. - If
True, the calibration is still in progress, and we do nothing. - If
False, the calibration has successfully finished.
- The second
-
Finalize the Process
- Once complete, we set a new boolean variable,
Complete Calibration, totrue. - We also reset
Start Calibrationtofalseto stop theTickevent from running this logic unnecessarily in the following frames. - At this point, you can use the
Complete Calibrationvariable to trigger UI animations, enable a "Continue" button, or automatically load the main game level.
- Once complete, we set a new boolean variable,
With the calibration complete, we need a way to receive the continuous stream of motion data from the controller. For this, we will use Unreal Engine's Enhanced Input System. This modern system provides a powerful and flexible way to handle complex inputs like the 3D vectors from our motion sensors.
We have created three distinct Input Actions to handle the different types of motion data provided by the plugin. This separation gives us the flexibility to use the raw data (Accelerometer, Gyroscope) or the combined, stabilized data (Rotator) depending on our needs.
-
IA_Accel(Accelerometer) 🎢- Purpose: Receives the raw linear acceleration data. This is useful for detecting shakes, jolts, or the direction of gravity.
-
Value Type:
Axis3D (Vector) -
Asset Path:
/Script/EnhancedInput.InputAction'/Game/Variant_Shooter/Input/Actions/GyroscopeAction/IA_Accel.IA_Accel'
-
IA_Gyro(Gyroscope) 🌀- Purpose: Receives the raw rotational velocity data. This tells you how fast and in which direction the controller is rotating.
-
Value Type:
Axis3D (Vector) -
Asset Path:
/Script/EnhancedInput.InputAction'/Game/Variant_Shooter/Input/Actions/GyroscopeAction/IA_Gyro.IA_Gyro'
-
IA_Rotator(Fused Orientation) 🎯-
Purpose: This is the action we will primarily use for aiming. It receives the stabilized orientation data (
Tiltvector) which is a fusion of both accelerometer and gyroscope data. This provides a smooth and stable rotation value, perfect for camera control. -
Value Type:
Axis3D (Vector) -
Asset Path:
/Script/EnhancedInput.InputAction'/Game/Variant_Shooter/Input/Actions/GyroscopeAction/IA_Rotator.IA_Rotator'
-
Purpose: This is the action we will primarily use for aiming. It receives the stabilized orientation data (
Now that we have our Input Actions, we need to tell the Enhanced Input system how to trigger them. This is done inside an Input Mapping Context (IMC). The IMC is where we create the link between a physical input from a device and the abstract actions we want to perform.
In this tutorial, we will focus on mapping the gyroscope's orientation data to our IA_Rotator action.
-
Open Your Input Mapping Context
- Navigate to your project's primary IMC, the one used for player controls during gameplay.
-
Add a New Mapping
- In the Mappings array, add a new element.
-
Configure the Mapping
-
Action: For the action property, select our previously created
IA_Rotator. -
Key: This is the most important step. Click the dropdown for the key and search for
Tilt. This is a special key provided by the Windows Dualsense Unreal Plugin that directly represents the fused orientation data (Pitch, Yaw, Roll) from the controller's motion sensors. You can typically find it under the "Gamepad Motion" or a similar category.
-
Action: For the action property, select our previously created
✨ Note: The
Tiltkey provides the combined and stabilized vector from the gyroscope and accelerometer, which is exactly what we need for smooth aiming.
This is where all the pieces come together. We will now create the logic that reads the gyroscope data from our Input Action and translates it into camera movement for the player. This logic is primarily handled in the BP_ShooterCharacter Blueprint.
The goal is to activate gyro aiming only when the player is Aiming Down Sights (ADS), which is typically triggered by holding the L2 button.
First, we need to capture the data from our IA_Rotator Enhanced Input Action.
In the Event Graph of BP_ShooterCharacter, add the event node for IA_Rotator. This event will fire on every frame that the controller reports motion, providing the stabilized Tilt data in its Action Value.

- The
Triggeredexecution pin provides a continuous stream of data. - The
Action Valueis a 3D vector containing thePitch(X),Yaw(Y), andRoll(Z) of the controller's orientation. - We store the X (Pitch) and Y (Yaw) values into local variables. As the comment in the image suggests, you could easily swap the Y (Yaw) pin for the Z (Roll) pin here if you prefer tilt-based horizontal aiming.
- The
is Gyro Aim Initializedbranch is a safety check to ensure this logic only runs after calibration is complete.
Raw sensor data can be jittery. To create a smooth and professional aiming experience, we need to process these raw values before applying them to the camera. This logic should be placed in a function or within the Event Tick, but only executed when the player is aiming down sights (when L2 is held down).
This processing involves calculating the movement delta per frame, applying a dead zone, and smoothing the result over time.

Here’s a breakdown of this crucial logic:
-
Calculate Delta (Rotator) 📐
- We first calculate the difference (
Delta) between the current gyro rotation and the rotation from the previous frame (Last Gyro Rotation). This gives us the precise amount of movement that occurred in the last frame, which is exactly what we need to add to our camera's rotation.
- We first calculate the difference (
-
Apply Dead Zone 🚫
- The
Apply Dead Zonefunction filters out tiny, unintentional movements. If the input is smaller than theDead Zonevalue, it's ignored. This is critical for preventing camera jitter when the player is trying to hold the controller still.
- The
-
Smooth the Input with
FInterp To✨- To prevent jerky and robotic camera movement, we use the
FInterp Tonode. This function smoothly interpolates the current aim value towards our target gyro value over time. -
Interp Speedis a key variable here. A lower value will make the aim feel "softer" and more smoothed, while a higher value will make it more responsive and 1-to-1.
- To prevent jerky and robotic camera movement, we use the
-
Store the Final Values 💾
- The final, smoothed Pitch (
Gyro Target Y) and Yaw (Gyro Target X) values are stored. These are the values that will be fed into theAdd Controller Pitch InputandAdd Controller Yaw Inputnodes to move the camera. - At the end, the current rotation is saved to the
Last Gyro Rotationvariable to be used in the next frame's delta calculation.
- The final, smoothed Pitch (
💡 Designer-Friendly: A key benefit of this setup is that all the important variables for tuning the aim feel (Dead Zone, Interp Speed, and even Float Curves if you choose to add them) can be exposed as editable variables. This allows a designer to tweak and perfect the aiming controls directly in the Unreal Editor without ever needing to recompile the Blueprint.
While our previous processing logic creates a functional aiming system, we can add one final stage to achieve a truly organic and responsive feel. Instead of directly applying the interpolated values to the camera, we can pass them through a Quaternion Spring Interpolation model.
This advanced technique simulates a physical spring connecting the camera's current rotation to the target rotation provided by the gyroscope. The result is an incredibly smooth motion with natural follow-through and settling, eliminating any hint of robotic jerkiness.

Here's how this final stage works:
-
Quaternion Spring InterpNode 🧬- This is the heart of our advanced smoothing. It takes the smoothed aim from our previous step as the
Currentrotation and the new, processed gyro input as theTarget. - It calculates a new camera rotation based on physical properties, creating a fluid transition.
- A
Spring Statevariable must be created and fed back into this node on each frame. This variable preserves the spring's momentum and velocity between ticks, making the simulation work correctly.
- This is the heart of our advanced smoothing. It takes the smoothed aim from our previous step as the
-
Tunable Physics Parameters 🔧
- The power of this approach lies in its exposed parameters, which allow for deep customization of the aiming feel:
-
Stiffness: Controls how quickly the camera tries to catch up to the player's aim. Higher values mean a tighter, more responsive feel. -
Critical Damping Factor: Prevents the "spring" from overshooting the target and oscillating back and forth. A value of1.0creates a critically damped spring that settles quickly. -
Mass: Adds a sense of weight and inertia to the camera movement.
-
- The power of this approach lies in its exposed parameters, which allow for deep customization of the aiming feel:
-
Set Control Rotation🏆- The final, beautifully smoothed
Return Valuefrom the spring interpolation is now used to drive the camera. We feed this rotator directly into theSet Control Rotationnode to apply the movement to the player's view.
- The final, beautifully smoothed
By adding this final layer of polish, you transform a simple gyro input into a high-fidelity aiming system that feels natural, intuitive, and satisfying to use. This concludes the core implementation of our ADS Gyro Aiming feature!
One of the most powerful features of this setup is the ability to fine-tune the gyroscope's behavior live while the game is running. This allows you to immediately feel the impact of every change, dramatically speeding up the process of perfecting your aiming controls.
- Start the game by pressing the Play button in the editor.
- Press the
F8key to eject from your character. This will give you a free-roaming spectator camera and unlock your mouse cursor. - In the World Outliner panel, select your
BP_ShooterCharacter. - With the character selected, go to the Details panel and search for
Gyro Setup.
You will now see all the key variables that control the aiming behavior, ready to be modified in real-time.

You can now experiment with:
- Sensitivity for Pitch and Yaw.
- The physics properties of the Spring Interpolation (
Stiffness,Mass,Damping). - Even swapping out the Float Curve assets on the fly.
A particularly useful feature is the Enum Cartesian Plane Selection. This allows you to isolate a single axis for testing. For example, you can set it to test only Yaw (X) or only Pitch (Y), making it much easier to tune each axis's sensitivity and smoothing individually.
Congratulations! You have now implemented a complete, highly customizable ADS Gyro Aiming system. By following these steps, you've learned how to properly calibrate the controller, process raw motion data, and apply advanced smoothing techniques to create a feature that provides a significant competitive edge and a deeply immersive experience for players.