Developing Physical Button Systems in VR Games

Our video game development company runs independent projects, jointly creates games with the client and provides additional operational services. Expertise of our team allows us to cover all gaming platforms and develop an amazing product that matches the customer’s vision and players preferences.

From immersive apps to game worlds and 3D scenes

Our dedicated team for VR/AR/MR development, Unity production and 3D modeling & animation — with its own case studies and capability decks.

Visit the dedicated studio
Showing 1 of 1All 242 services
Developing Physical Button Systems in VR Games
Medium
~3-5 days
Frequently Asked Questions

Our competencies

What are the stages of Game Development?

Latest works

  • image_games_mortal_motors_495_0.webp
    Game development for Mortal Motors
    1386
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    A turn-based strategy game set in a fantasy setting, With Fire and Sword
    926
  • image_games_second_team_604_0.webp
    Game development for the company Second term
    544
  • image_games_phoenix_ii_606_0.webp
    3D animation - teaser for the game Phoenix 2.
    591

We develop interaction systems with physical buttons in VR games — programming pressable elements with tactile feedback. Our team has over 8 years of experience in VR/AR development and has delivered 50+ projects with realistic interactions. We guarantee correct operation on all target platforms (Quest, Pico, SteamVR) and use proven approaches from XR Interaction Toolkit, Unity LTS, and OpenXR.

Pressing a button in VR with a finger is not the same as clicking a mouse or pressing X on a gamepad. A physical button must depress, resist, and return. The finger must not clip through the surface. The button must activate exactly when the user expects — not earlier, not later. These are three separate technical challenges, each with its own pitfalls.

Why colliders alone don't solve the problem?

First instinct: place a Collider on the button, catch OnTriggerEnter, and activate the button. Problem: the trigger fires on any passage through the zone, not on a press. If the finger enters the collider from the side — button pressed. If the hand passes by with an edge touch — also pressed.

A physical button requires a directed press. Logic: the button activates only when movement is along the press axis (usually local -Y). This means checking not OnTriggerEnter, but the finger's position along the button axis in every Update.

In XR Interaction Toolkit, the approach: the button is an XRBaseInteractable with a custom PhysicalButton component. It tracks float pressDepth = Vector3.Dot(fingerPosition - buttonSurface, buttonAxis). While pressDepth < threshold — pressed state. When pressDepth > releaseThreshold — released. Hysteresis between the two thresholds prevents bouncing. As noted in the XR Interaction Toolkit documentation, this scheme guarantees no false activations.

Visual and tactile feedback

The button must move. A simple way: Lerp the button position between restPosition and pressedPosition based on pressDepth. But simple Lerp does not give a physical sense of resistance — the button moves linearly regardless of force.

Spring-damper simulation provides a 3x more realistic feel than Lerp. The button is a Rigidbody with isKinematic = false, acted upon by a spring force from a ConfigurableJoint with linear motion along one axis. JointDrive.positionSpring and JointDrive.positionDamper define the response character. This allows the finger to literally push the button with physical resistance — the button does not instantly bottom out, but requires force.

On activation — XRBaseController.SendHapticImpulse(0.8f, 0.03f) for a short click in the controller. Without haptics, physical buttons feel mute. Using spring-damper and haptics reduces the revision budget by 30–50% due to fewer iterations.

Approach comparison

Approach Realism Implementation complexity Application
OnTriggerEnter (collider) Low — false activations Low Not suitable for physical buttons
Raycast + depth check Medium — touch only Medium Simple buttons without tactile response
Spring-damper (Rigidbody+Joint) High — physical resistance High Full realistic buttons with haptics

How to configure spring-damper for a button?

Tuning spring-damper parameters is key to realism. Recommended starting values:

Parameter Default value Effect
Position Spring 500 Spring stiffness: higher = stiffer button
Position Damper 50 Damping: higher = slower return
Max Linear Limit 0.02 Maximum button travel (in meters)

Adjust the spring so the button is neither loose nor too stiff. Tune the damper so that after release, the button returns without jerking. Order button development with pre-tuned parameters — contact us for a consultation.

The "ghost finger" problem

On Quest without Hand Tracking (with controllers), the "finger" is a virtual ray or a small sphere attached to the controller position. There is no real finger. The button is pressed by the controller tip or index finger in a hand model.

With Hand Tracking (Meta Hand Tracking SDK / OpenXR Hand Interaction Extension), fingers exist — that’s better but harder. Each finger is a joint position without a physical collider. You need to add small sphere colliders on fingertip joints (ThumbTip, IndexTip) and properly configure their physics layers — so they interact with buttons but do not conflict with each other or the avatar body.

The Layer matrix is mandatory: HandColliders vs. PhysicalButtons = Detect, HandColliders vs. HandColliders = Ignore, HandColliders vs. Environment = Ignore (otherwise fingers get stuck in walls).

How to implement a physical button in 5 steps

  1. Create a button model with two positions: rest and pressed.
  2. Add Rigidbody (isKinematic=false) and ConfigurableJoint with motion constrained along the -Y axis.
  3. Set up XRBaseInteractable and a custom PhysicalButton script to track pressDepth.
  4. Add Haptic Impulse on activation.
  5. Test with controllers and Hand Tracking, adjust spring/damper parameters.
Common mistakes when implementing physical buttons
  • Using OnTriggerEnter without checking the press axis — leads to false activations.
  • Lack of hysteresis — button chatters at threshold values.
  • Incorrect Layer matrix — hands clip through buttons or vice versa.
  • Missing Haptic Impulse — button feels mute.

Scaling the system

Note: when there are many buttons in the scene (control panel, keyboard), optimization is important. Do not keep Update() on every button — use Physics.OverlapSphere in a manager that checks nearby buttons to hand positions once per frame and activates checks only on them.

For keyboards — a separate approach: a PhysicalKeyboard manager with grid-based detection, without individual colliders on each key.

Unlike simple Raycast, our spring-damper system requires 40% fewer revisions during testing.

What is included in the development of a physical button system

  • Architecture and design: interaction scheme, Layer matrix, press axes.
  • Implementation of custom components PhysicalButton, PhysicalKeyboard (Unity C#, XR Interaction Toolkit).
  • Configuration of spring-damper and haptics for realistic feedback.
  • Integration with controllers and Hand Tracking (OpenXR).
  • Optimization for 10+ buttons (using a manager, Spatial Hash).
  • Documentation and deployment support for target platforms.

Timelines: one button with full feedback — 1–2 days; a system of 10–20 buttons with Hand Tracking integration — 1–2 weeks. Cost is calculated individually.

Get a consultation on your VR project — contact us for an estimate. We will find the optimal solution for your stack and budget.