We use cookies on this site to enhance your user experience

Gamepad Haptic Feedback

Gamepad Haptic Feedback

Sep 25 2019, 2:02 PM PST 5 min

The Xbox One controller and some other USB gamepad controllers have motors built in to provide haptic feedback. Adding rumbles and vibrations can greatly enhance a game’s experience and provide subtle feedback that is hard to convey through visuals or audio. Roblox provides a service to developers called the HapticService to handle haptic feedback.

Checking for Vibration Support

Not all controllers support vibration so it is important to check if the plugged-in controllers have support before attempting to use the ClassLink|HapticService. To check if a given controller has rumble support at all, you can call HapticService/IsVibrationSupported

local HapticService = game:GetService("HapticService")
local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)

Once you have checked if a gamepad supports vibration, you should also check if it supports the motors you intend to use. On XBox One the controller has 4 motors:

  • Large: in the left side of the controller. Good for generic rumble.
  • Small: in the right side of the controller. Good for more subtle rumbles(tire slipping, electric shock, etc.)
  • Left Trigger: underneath the left trigger. Good for braking, gun reloading, etc.
  • Right Trigger: underneath the right trigger. Good for recoil, acceleration, etc.

On PC you will have less guarantee of what kind of controller the user has. Many only support the Large and Small motors (no triggers). You can use HapticService/IsMotorSupported to see if the user’s controller supports the motor you want to use.

local HapticService = game:GetService("HapticService")
local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)
local largeSupported = false
if isVibrationSupported then
	largeSupported = HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)

Turning on Motors

Once you have confirmed that a user’s gamepad supports vibration you can start using the gamepad motors. You can use HapticService/SetMotor to turn on a specific motor on a gamepad. This function takes the gamepad and the amplitude of the vibration as arguments. The amplitude can be any value between 0 and 1 (0 being no vibration, 1 being max vibration).

local HapticService = game:GetService("HapticService")
HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large, .5)

You can also use HapticService/GetMotor to get the current vibration amplitude of a given motor.

local HapticService = game:GetService("HapticService")
print(HapticService:GetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)
-- Services
local HapticService = game:GetService("HapticService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

-- Make sure we are running in a LocalScript.
local player = Players.LocalPlayer
assert(player,"This should be running in a LocalScript!")

-- Setup Haptic Feedback Listener
local function updateHapticFeedback()
	-- Check if we currently have a character.
	local character = player.Character
	if character then
		-- Do we have a Humanoid?
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if humanoid then
			-- Are we in a vehicle seat?
			local seatPart = humanoid.SeatPart
			if seatPart and seatPart:IsA("VehicleSeat") then
				-- Measure the current speed of the vehicle by taking the magnitude of the seat's velocity.
				local speed = seatPart.Velocity.Magnitude 
				-- Measure the current throttle from the user.
				local throttle = math.abs(seatPart.ThrottleFloat)
				-- Compute how much the controller should be vibrating.
				local vibrationScale = math.min(1, (speed * throttle) / seatPart.MaxSpeed)
				-- Apply the vibration.
				HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, vibrationScale)
				-- Return so the motor doesn't get reset.
	-- If nothing is happening, turn off the motor.
	HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, 0)

-- Connect our haptic feedback listener to be updated 60 times a second.