⚠ Preview docs — built from the develop branch and may be unstable. Go to the stable docs.

Input.HapticCaps

static InputHapticCaps HapticCaps(InputHaptic output)

Returns the playback modes the given haptic output supports right now. The result depends on which controller is active and which OpenXR extensions are available, so it can change at runtime whenever the active OpenXR interaction profile changes — typically when the user picks up, sets down, or swaps a controller. Code that relies on HapticWaveform or HapticCurve should check this first and fall back to HapticPulse when the relevant capability bit is missing.

   
InputHaptic output Which haptic output to query.
RETURNS: InputHapticCaps A flags value with one bit per supported playback mode, or None if the output isn’t currently bound.

Examples

Driving haptics from controller velocity

This shows how to map a continuous physical signal (here, the controller’s grip-pose velocity) onto haptic output. There are two paths: a simple per-frame HapticPulse that works on every device, and a streaming HapticWaveform path that’s used when XR_FB_haptic_pcm is available.

void StepProcedural(InputHaptic output)
{
	Handed   hand    = output == InputHaptic.LController ? Handed.Left : Handed.Right;
	InputPose pose   = output == InputHaptic.LController ? InputPose.LGrip : InputPose.RGrip;
	PoseState state  = Input.PoseState(pose);
	if (!state.IsTracked()) { haveLastPos = false; return; }

	Vec3 pos = Input.Pose(pose).position;
	if (!haveLastPos) { lastGripPos = pos; haveLastPos = true; return; }

	float speed   = (pos - lastGripPos).Length / Math.Max(0.001f, Time.Stepf);
	lastGripPos   = pos;
	float intensity = MathF.Min(1, speed / 2.0f); // ~2 m/s saturates

	InputHapticCaps caps = Input.HapticCaps(output);
	if ((caps & InputHapticCaps.Waveform) != 0)
	{
		// Streaming path: synthesize one frame's worth of samples at the
		// device's preferred rate, append onto the existing stream.
		float r     = Input.HapticPreferredRate(output);
		if (r <= 0) r = 4000;
		int   count = (int)(r * Time.Stepf);
		if (procBuffer.Length != count) procBuffer = new float[count];
		for (int i = 0; i < count; i++)
			procBuffer[i] = MathF.Sin(2 * MathF.PI * 220 * i / r) * intensity;
		Input.HapticWaveform(output, procBuffer, r, append: true);
	}
	else if ((caps & InputHapticCaps.Pulse) != 0)
	{
		// Fallback path: per-frame pulse with current intensity.
		Input.HapticPulse(output, 0, intensity, Time.Stepf);
	}
}




Found an issue with these docs, or have some additional questions? Create an Issue on Github!