Written by: Ellie Na (2026)
Unity's built-in TouchScreenKeyboard API doesn't work reliably in VR, it's designed for flat mobile screens, not 3D hand-tracked environments. This page covers how to build a fully custom VR keyboard from scratch: physical poke interaction, automatic layout generation, and direct text injection into a TMP_InputField.
XR Poke Interaction already set up (see XR Poke Interaction page)
(The keyboard uses the same SimpleTouchButton + HandColliderSetup system from the page)
TextMeshPro (TMP) installed (keyboard targets TMP_InputField)
TouchScreenKeyboard.Open() is Unity's built-in API for triggering a system keyboard. In VR it either doesn't appear, appears flat on the screen (not in world space), or can't be interacted with via hand tracking. It also gives you no control over layout, style, or behavior.
The custom approach here instead:
Lives in world space alongside your other UI
Is pressed with the same finger poke system as every other button
Directly manipulates TMP_InputField.text. no event routing needed
Can be generated automatically with one click in the Editor
There are three scripts involved
VRKeyboard.cs that manages the target input field and processes key input
VRKeyButton.cs that sits on each key, knows its key type and value, calls the keyboard
VRKeyboardGenerator.cs that auto-generates the full keyboard layout as editor tool
Create an empty GameObject in the Hierarchy, name it VRKeyboard - Add the VRKeyboardGenerator component - Assign the VRKeyboard reference in the Inspector - Right-click the component header 'Generate Keyboard'
The full layout is created instantly as child GameObjects, all saved in the scene, not generated at runtime.
Run in your headset!
These are the issues I encountered while building this keyboard and how I troubleshot them.
#1 Keys don't respond to pokes?
Confirm BoxCollider on each key has Is Trigger = true
Check HandColliderSetup is active on both hands
Verify SimpleTouchButton.onButtonPressed is wired to VRKeyButton.OnKeyPoked()
#2 Text appears in wrong input field?
SetTargetInputField() must be called each time you open the keyboard for a new field — the target is not set automatically
#3 Keyboard not visible in headset?
Confirm the keyboard is a child of (or positioned within) a World Space Canvas
Check it's included in Build Settings scenes
# 4Generator doesn't appear in right-click menu?
The [ContextMenu] attribute only works in the Unity Editor and make sure you're right-clicking the component header in the Inspector, not in the Hierarchy