Unity 6.6 Input System Rebinding Asset Preflight for Steam Deck Verified Retests (2026 Programming Guide)

Your keyboard rebinding screen shows B for jump. The pause menu glyph shows A. Steam Input still maps jump to south face. The Deck reviewer presses A and your character crouches. That is not a “Deck bug”—it is three sources of truth for the same PlayerInput action.
Unity 6.6 LTS with the Input System package is the default stack for 2026 PC indies resubmitting Steam Deck Verified after a first fail. This Programming & Technical guide is a ninety-minute preflight to align InputActionAsset, on-disk rebinding JSON, UI glyph tables, and Steamworks action sets before you burn a review cycle.
Pair it with the narrative 48-hour Deck recovery case study and the failure taxonomy in nine submission fails—this article is the Unity wiring those pieces assume.
Why this matters now (May 2026)
- Verified retest volume — Spring–summer 2026 cohorts report input/glyph notes on second submissions when rebinding shipped after first fail without a preflight pass.
- Unity 6.6 package drift — Input System 1.11+ defaults and sample assets moved; teams upgrading from 6.5 sample projects copy outdated
RebindSaveLoadpatterns. - Fest demo pressure — October Next Fest builds on Deck hardware in reviewer queues; mislabeled glyphs read as “broken controls” in minutes of play.
- Evidence culture — Publisher diligence and cert-style reviews ask for repro steps; unversioned rebinding JSON cannot be replayed.
Direct answer: One InputActionAsset reference everywhere → versioned rebinds_v2.json → glyph lookup keyed by binding path → Steam Input manifest generated from the same action map → ninety-minute checklist before upload.
Who this is for
- Unity 6.6 LTS projects using Input System (not legacy
Input Manageralone) - Teams resubmitting Steam Deck Verified after glyph or binding notes
- Solo / 2–3 person studios without a dedicated input programmer
Not for: pure legacy input projects (migrate first), or games with zero remapping and zero Steam Input (lighter bar, still verify defaults).
Prerequisites
- Input System package 1.11+ (match Unity 6.6 lockfile)
PlayerInputor customInputActionAssetin production scenes- Steamworks SDK integrated with published controller config (or plan to publish)
- Deck dev kit or borrow hardware for final 15 minutes of preflight
release-evidence/01-build/input-preflight/folder created
Architecture — one source of truth
InputActionAsset (project)
├─ PlayerInput component (scene)
├─ Rebind UI (reads/writes binding overrides)
├─ GlyphResolver (binding path → sprite)
├─ rebinds_v2.json (persistent overrides)
└─ steam_input_v2.vdf (exported action names ↔ action map)
Forbidden: duplicate InputActionAsset copies in Resources/ and Addressables/ with different GUIDs.
Step 1 — Asset audit (20 minutes)
Checklist
- [ ] Single
InputActionAssetassigned inPlayerInputon player prefab - [ ] No duplicate action map names across assets
- [ ] All gameplay actions use action names stable since last public build
- [ ] UI uses
InputActionReferenceassets, not hard-coded KeyCode in rebinding screen - [ ]
Project Settings → Player → Active Input Handling= Input System Package or Both (document if Both)
Find drift quickly
// Editor menu or one-off debug — lists PlayerInput assets in build scenes
#if UNITY_EDITOR
public static void AuditPlayerInputs() {
foreach (var pi in Object.FindObjectsByType<PlayerInput>(FindObjectsSortMode.None))
Debug.Log($"{pi.gameObject.name} asset={pi.actions?.name} default={pi.defaultActionMap}");
}
#endif
Log output goes in release-evidence/01-build/input-preflight/audit-log.txt.
Step 2 — Rebinding save format (25 minutes)
Version your JSON
{
"schema": 2,
"assetGuid": "a1b2c3d4e5f6789012345678abcdef01",
"bindings": [
{
"action": "Player/Jump",
"bindingIndex": 0,
"overridePath": "<Gamepad>/buttonSouth"
}
]
}
Rules:
schemaincrements when you rename actions or reorder mapsassetGuidmust match currentInputActionAsset— on mismatch, discard saves and show one-time migration dialog- Never store human-readable KeyCode alone without
overridePath
Load pattern (runtime)
public void LoadRebinds(string json) {
var data = JsonUtility.FromJson<RebindSaveData>(json);
if (data.schema < CurrentSchema || data.assetGuid != _asset.guid.ToString())
return; // fail safe — defaults only
foreach (var b in data.bindings)
_asset.FindAction(b.action)?.ApplyBindingOverride(b.bindingIndex, b.overridePath);
}
PlayerPrefs migration
If you shipped schema: 1 in 2025:
- Detect old key on boot
- Map known actions only; drop unknown rows
- Write
rebinds_v2.json; delete old key - Log migration in
release-evidence/01-build/input-preflight/migration-notes.md
Step 3 — Glyph resolver (20 minutes)
Glyphs must key off effective binding path after overrides, not default keyboard labels.
public Sprite ResolveGlyph(InputAction action, int bindingIndex) {
var path = action.bindings[bindingIndex].effectivePath;
if (_glyphTable.TryGetValue(path, out var sprite))
return sprite;
return _fallbackGlyph;
}
Glyph table minimum rows (Deck-relevant)
| effectivePath | Sprite set |
|---|---|
<Gamepad>/buttonSouth |
A / cross (document platform style) |
<Gamepad>/buttonEast |
B / circle |
<Gamepad>/leftStickPress |
L3 |
<Gamepad>/rightTrigger |
R2 |
<Keyboard>/space |
KB Space |
Steam Deck Verified expects on-screen prompts to match actual remapped controls during the review session.
UI pass
Walk pause menu, tutorial prompts, and interact hints—grep for legacy Text showing "Press E" without resolver.
Binding groups and control schemes
Unity’s control schemes (Keyboard&Mouse, Gamepad, Touch) are not decorative—they decide which bindings appear active per device. Preflight checks:
| Check | Why Deck cares |
|---|---|
| Every gameplay action has a gamepad binding in the Gamepad scheme | Missing row → fallback to keyboard paths on Deck |
PlayerInput.neverAutoSwitchControlSchemes documented |
Auto-switch during rebinding UI confuses testers |
| UI map uses same scheme rules as gameplay | Pause menu stuck on keyboard scheme shows WASD glyphs |
bindingMask not left on from debug code |
Masks silently drop Deck bindings |
Sample: enforce gamepad binding exists
void ValidateGamepadBindings(InputActionAsset asset) {
foreach (var map in asset.actionMaps)
foreach (var action in map.actions) {
var hasPad = false;
foreach (var i in action.bindings)
if (i.effectivePath.Contains("Gamepad")) hasPad = true;
if (!hasPad)
Debug.LogError($"Missing gamepad binding: {map.name}/{action.name}");
}
}
Run in Editor before release candidate; zero errors required.
Rebinding UI — safe override application
Official samples often call PerformInteractiveRebinding. Preflight the UI layer:
- Disable gameplay maps during rebind capture (only UI map active).
- Cancel rebind if user backs out—do not partial-apply.
- Refresh all glyph widgets after
onComplete. - Serialize immediately to disk; do not rely on OnDestroy.
- Show effective path string in debug builds for QA screenshots.
Anti-pattern: duplicate listeners
// ANTI-PATTERN — doubles input on Deck
void OnEnable() {
_jumpAction.performed += OnJump;
_jumpAction.performed += OnJump; // copy-paste from merge
}
Deck reviewers report “double jump” or “unresponsive” when events stack.
Steam Deck specific paths
Effective paths on Deck often include:
<XInputController>/buttonSouth<DualShockGamepad>/buttonSouth(some Proton paths)<SteamController>when Steam Input injects virtual device
Your glyph table needs one sprite per logical face button, not per physical device string—normalize paths:
static string NormalizePath(string path) {
if (path.Contains("buttonSouth")) return "<Gamepad>/buttonSouth";
if (path.Contains("buttonEast")) return "<Gamepad>/buttonEast";
// extend for north/west, shoulders, triggers
return path;
}
Without normalization, rebinding to south face updates gameplay but UI still shows keyboard Space.
Step 4 — Steam Input parity (15 minutes)
- Export action set names that match
InputActionAssetmap names (case-sensitive). - Publish config in Steamworks before uploading build.
- In-game, enable Steam Input API when available; do not fight Steam with raw XInput-only paths unless documented.
- Verify desktop vs Deck default action sets if you ship templates.
Capture steam_input_v2.vdf hash in release-evidence/01-build/input-preflight/.
Ninety-minute execution map
| Block | Time | Output |
|---|---|---|
| Asset audit | 0:00–0:20 | audit-log.txt |
| JSON schema + migration | 0:20–0:45 | rebinds_v2 sample + migration note |
| Glyph resolver sweep | 0:45–1:05 | screenshot grid per scene |
| Steam Input export | 1:05–1:20 | vdf hash |
| Deck hardware spot-check | 1:20–1:30 | 5-line result in README |
Deck hardware spot-check (non-negotiable last 10 minutes)
On real Deck (not Editor only):
- Factory-reset controls in game settings
- Complete first-room jump + interact + pause map
- Rebind jump to east face; confirm gameplay and glyph update
- Restart app — bindings persist
- Open Steam overlay — no double-input ghosting
Fail any step → do not upload retest build.
Integration with release-evidence
release-evidence/01-build/input-preflight/
README.md
audit-log.txt
migration-notes.md
glyph-screenshots/
steam_input_vdf_hash.txt
deck-spotcheck-YYYY-MM-DD.md
Link folder from release-evidence taxonomy README.
Common failures (2026 forum patterns)
| Symptom | Likely cause | Fix |
|---|---|---|
| Glyph shows keyboard on Deck | Resolver ignores gamepad path | Filter by IsGamepad() |
| Rebind works until restart | Saving KeyCode not override path | schema 2 JSON |
| Steam chord + game action double-fire | Both Steam and game listen | Steam Input consume rules |
| Pause map wrong | Separate UI action asset | Merge assets |
| Reviewer sees default only | Rebind file in StreamingAssets stale | Bump schema, clear cache |
Fullscreen and focus (adjacent Deck fails)
Input preflight does not replace fullscreen checks from the case study:
- Borderless vs exclusive on Deck
- Focus trap when rebinding overlay open
- Cursor visibility when using gamepad-only UI
Log fullscreen mode in same README.md so reviewers see one packet.
PlayerInput notification behaviors
PlayerInput defaults changed across sample versions. Document your choice in README:
| Behavior | Use when |
|---|---|
InvokeUnityEvents |
Designer-friendly; watch duplicate UnityEvent wiring |
SendMessages |
Legacy; easy to miss message handlers on Deck builds |
BroadcastMessages |
Wide blast; can hit wrong objects |
CSharpEvent |
Preferred for code-first teams; explicit subscribe/unsubscribe |
Preflight: one behavior per project, grep for orphaned OnJump messages.
Action map enable/disable during scenes
Floor loaders and cutscenes often disable maps incorrectly:
// Safer pattern — stack disable reasons
void PushDisable(string reason) {
_disableStack.Add(reason);
_playerInput.DeactivateInput();
}
void PopDisable(string reason) {
_disableStack.Remove(reason);
if (_disableStack.Count == 0)
_playerInput.ActivateInput();
}
Deck fail: player exits cutscene with UI map still active—jump bound to menu confirm.
Testing matrix (Editor + Deck)
| Case | Editor | Deck |
|---|---|---|
| Fresh install defaults | ✓ | ✓ |
| Rebind jump → persist restart | ✓ | ✓ |
| Reset to defaults | ✓ | ✓ |
| Steam overlay open | n/a | ✓ |
| Quick resume from sleep | n/a | ✓ |
| External keyboard attached | optional | optional |
Sleep/resume on Deck exposes bindings loaded before suspend without re-resolve—force GlyphResolver refresh on OnApplicationPause(false).
Evidence screenshots partners expect
Capture six PNGs into glyph-screenshots/:
- Title screen — gamepad prompts visible
- Settings rebinding row — before change
- Same row — after remapping south→east
- Gameplay HUD — matches remapped jump
- Steam Input overlay showing published config
- Build version + schema in corner (debug overlay OK)
Patch notes and schema bumps
When schema increments, two-pass patch notes must say:
- “Controller bindings reset once” if migration drops saves
- “Steam Input config updated” if vdf changed
Cross-reference publisher milestone checklists if contract requires notice.
Link to replay and cert artifacts
If cert asks for reproduction of “jump wrong button,” attach:
input.jsonfrom deterministic replayrebinds_v2.jsonfrom same sessionschema+assetGuidheader
Reviewers reproduce faster than video alone.
Unity 6.6 upgrade notes (from 6.5)
Teams upgrading mid-2026 should re-run preflight when:
- Input System package minor bumps
PlayerInputprefab overrides change in merge- New Input System samples imported over old
RebindSaveLoad
Diff Packages/manifest.json and packages-lock.json into migration-notes.md.
Accessibility and remapping
Remapping is an accessibility feature in 2026 store conversations:
- Do not gate story progress behind impossible defaults
- Offer hold/toggle options where industry expects (sprint, aim)
- Document remapping in store accessibility blurb only if true
Misclaiming remapping while shipping hard-coded keys hurts truth audits.
Extended FAQ
Composite bindings?
Each part of composite needs glyph strategy—or show composite icon. Test chord prompts on Deck (Steam + game).
Local multiplayer?
Separate PlayerInput instances need separate rebinds_v2_player{n}.json files—never share one JSON.
Input System vs legacy in same scene?
Pick one for ship week; hybrid is retest poison.
Epic / GOG builds?
Steam Input section is Steam-specific; duplicate preflight for other SDKs if shipped.
CI hook (optional, 30 lines)
# conceptual
- run: unity -batchmode -executeMethod InputPreflightCI.Run -quit
# fails if multiple PlayerInput assets or schema mismatch in test scene
Even a manual preflight checklist beats no automation.
Godot teams (pointer only)
Godot 4.5 uses InputMap + custom remappers—not this guide. See threaded loader for performance siblings; Deck glyph discipline still applies to on-screen prompts.
Operating review tie-in
Block 1 Engineering row during retest week:
Input preflight: pass/fail- Build hash tested on Deck
- Open glyph defects count
FAQ
We use Both Input Manager and Input System?
Document in README; preflight both paths or migrate to System-only before Verified retest.
Can we skip rebinding for review?
If shipping rebinding in production, review build must include it. If review-only branch without rebinding, label branch honestly—do not diverge from public default branch without note.
Does this fix performance TDP spikes?
No—pair with TDP profiling pass.
Android gamepad rebinding?
Same JSON discipline; different glyph sheet—add rows before mobile ship.
Related internal links
- Deterministic replay hooks — capture input.json beside rebinding version
- Build manifest diff gates — catch wrong input asset in patch
- 25 Deck resources
- Truth audit — store copy “full controller support” vs build
Deep dive — effectivePath vs path
Input System exposes both default binding paths and effective paths after overrides. Every glyph and QA script must use effective:
for (int i = 0; i < action.bindings.Count; i++) {
var b = action.bindings[i];
Debug.Log($"{action.name}[{i}] path={b.path} effective={b.effectivePath} override={b.overridePath}");
}
Dump this log on Deck after rebinding; attach to audit-log.txt. Reviewers asking “what did you think jump was?” get a one-file answer.
Interaction with InputUser and multiplayer
InputUser pairing matters when multiple devices connect:
- Deck built-in controls = one user
- Docked USB keyboard = second user only if game supports local MP
- Accidental double
InputUsercreation on scene load duplicates actions
Preflight: log InputUser.all.Count on main menu after three scene reloads—must match design (usually 1 for single-player).
OnScreenStick and touch overlays
Mobile or touch overlays on Deck (rare but present in hybrid builds) need separate control scheme rows. If touch overlays visible on Deck by bug, disable via platform check:
#if !UNITY_ANDROID && !UNITY_IOS
touchOverlay.SetActive(false);
#endif
Deck Verified expects primary interaction via handheld controls, not phantom touch UI.
Timing: when to run preflight in your ship calendar
| Milestone | Run preflight? |
|---|---|
| Weekly internal RC | Smoke only (audit log) |
| Pre-Next-Fest demo branch | Full ninety minutes |
| Post-rejection retest | Full + Deck spot-check |
| Hotfix one-line gameplay | Re-run if touch input assets |
| Marketing trailer capture | Verify glyphs in capture build hash |
Align with capsule iteration calendar so store videos show correct face buttons.
Troubleshooting decision tree
Reviewer says wrong button?
├─ Gameplay wrong, glyph right → binding override not applied (JSON load)
├─ Glyph wrong, gameplay right → resolver uses path not effectivePath
├─ Both wrong only on Deck → Steam Input layer / scheme mask
├─ Both wrong everywhere → duplicate action assets
└─ Intermittent → double event subscription or map not re-enabled
Work tree left-to-right; do not start with Proton theories before logging effective paths.
Sample README for evidence folder
# Input preflight — build 518
- Unity 6.6.0f1, Input System 1.11.2
- Schema 2, assetGuid a1b2…
- Deck spot-check 2026-05-16: PASS (5/5)
- Steam Input vdf sha256: …
- Known limitation: none
Contrarian note
Teams sometimes disable remapping for retest to “reduce variables.” If players get remapping in production, reviewers must too—otherwise you ship a different control contract than you tested.
Post-retest maintenance
After Verified clears:
- Freeze
InputActionAssetaction names until next major version - Add preflight to operating review Block 1 when input assets change
- Re-export Steam Input vdf on any new action
- Store last-pass
deck-spotcheckdate inrelease-evidence/01-build/input-preflight/so Q3 diligence zips show ongoing discipline, not one heroic week
Glossary
| Term | Meaning |
|---|---|
InputActionAsset |
Container for maps, actions, bindings |
effectivePath |
Path after overrides and interactions |
schema |
Version of saved rebind JSON |
glyph |
On-screen prompt sprite |
Steam Input |
Steamworks controller abstraction layer |
| Preflight | Pre-upload validation, not postmortem |
Printable checklist (upload gate)
- [ ] Single
InputActionAsset - [ ]
rebinds_v2.jsonschema + guid check - [ ] Migration from v1 logged
- [ ] Glyph resolver on all prompts
- [ ] Steam Input vdf matches map names
- [ ] Deck spot-check 5/5
- [ ] Evidence folder committed
- [ ] Patch notes mention input schema bump if player-facing
Editor vs player build parity
Confirm Development Build and Release Build share the same InputActionAsset addressables labels. A common 2026 slip: Editor references asset A while IL2CPP player strips asset B. Build hash 518 preflight must use the same artifact uploaded to Steam branch default or fest-demo.
Hold interactions and rebinding
Actions using Hold or Press interactions need rebinding UI that preserves interaction mode—swapping only the binding path while dropping Hold causes “button works in menu, not in game” Deck reports. Document interaction type in rebinds_v2.json if your save format extends schema 3 later.
Close: Steam Deck Verified retests in 2026 are often won in the boring layer—one action asset, versioned overrides, honest glyphs, and Steam Input parity. Run this ninety-minute Unity 6.6 preflight before you upload; reviewers should never be the first humans to discover your rebinding JSON still targets last month’s action map. Ship the evidence folder beside the build so the second submission is a receipt, not a debate—and keep effectivePath logs so the third submission never happens.