Fit Mode

In short

Fit Mode is a slider panel docked on the Customize stage. SOCKET edits where every item of a slot hangs on the model, ITEM edits one item’s own nudge, and in the BATS category SOCKET edits how every bat sits on the swing pivot. Changes apply live; nothing is written until SAVE.

How it works

Opening it

  • Press Play, open CUSTOMIZE, then click FIT in the top bar (Editor only; it reads FIT: ON while open), or press Ctrl+Shift+F (any build, including release builds).
  • Esc, CLOSE, Ctrl+Shift+F again, or opening a top-bar popup closes it. Leaving the Customize screen closes it too.
  • While it is open, hover try-on and keyboard panning are off, and the camera frames the slot being edited.

The panel

FIT MODE title and a DEV ONLY pill; a label of what is edited; SOCKET / ITEM; six sliders; RESET / AUTO-FIT; SAVE / CLOSE; a yellow note after SAVE or AUTO-FIT. A yellow ring with a blue forward tick marks the socket (or the bat pivot).

The target follows the Customize category (HATS, GLASSES, SHOES, BATS) and the selected tile.

ModeTarget classEditsSlidersSize range
SOCKET (hat, glasses, shoes)SocketFitTargetThe model’s socket in its CharacterFitProfile. Every item of that slot follows. Shoes edit both feet, the right one mirrored.UP, FORWARD, SIDEWAYS (nudges in metres from the values at open), SIZE, TIP FWD, TURN0.05 to 1.2 m
ITEMItemFitTargetThe selected item’s own offset, rotation, scale.absolute UP, FORWARD, SIDEWAYS, SCALE, TIP FWD, TURN0.3x to 3x
SOCKET in BATSBatFitTargetBatModelLibrary.modelOffset, modelRotation, modelScale for every bat model.UP, SIDEWAYS, ALONG BAT, SCALE, TIP UP, TURN0.5x to 2x
  • RESET goes back to the values when the panel opened.
  • AUTO-FIT (sockets only) replaces the socket with the automatic fit from FitMeasurer; the sliders restart from there. Not saved.
  • ITEM in BATS says bats have no per-item nudge.

Where SAVE writes

TargetIn the EditorIn a build
SocketThe CharacterFitProfile asset (SetDirty + SaveAssets)persistentDataPath/fit-overrides.json
Item that is a real assetThat CosmeticDefinition assetfit-overrides.json
Item built in code (DefaultContent)Assets/_Project/Resources/FitOverrides.json (committed)fit-overrides.json
BatsThe BatModelLibrary assetfit-overrides.json

At boot, FitOverrides.LoadAndApply reads Resources/FitOverrides.json, and in a build also fit-overrides.json on top, then applies both to the content, the character library’s fit profile and the bat library, before any batter is built. The local file is ignored in the Editor, so a build’s experiments never leak into the project. Saves accumulate (upsert by profile + slot + side, item id, or the one bat entry).

Fit profiles and the automatic fit

  • CharacterFitProfile (ScriptableObject): the character prefab, headHeight, and SocketFit entries (slot, side Center / Left / Right, Humanoid bone, bone-local position and euler, size). ToAnchors(animator) turns it into CosmeticAnchors. Its version bumps on every edit so a running batter re-hangs cosmetics.
  • FitMeasurer.Measure is the automatic fit: head mesh bounds give the top of the head and the eye line; foot and toe bones give the shoes; “forward” is the hips axis that matches the way the legs face.
  • Tools > Home Run Derby > Generate Fit Profile For Batter (FitProfileTools.GenerateForBatter): poses the CharacterLibrary.batterPrefab in the stance idle, measures it, and writes Assets/_Project/Content/Characters/<prefab>_Fit.asset, then assigns it to the library.

Built to be reused

IFitTarget and FitValues hold no UI, so the module can move to another game with different data behind it.

Numbers

WhatValueWhere to tune
Panel width300FitModeView.PanelWidth
Nudge range+-0.25 mFitModeView.NudgeRange
Tilt range+-60 degFitModeView.TiltRange
Note shown for2.5 sFlashSeconds
Camera distance while fitting0.9 (bats 1.7)CustomizeView.FitFrameDistance, FitFrameDistanceBat

In the code

FileWhat it does
Scripts/FitMode/FitModeView.csThe panel, retargeting, the socket ring.
Scripts/FitMode/IFitTarget.csFitValues, IFitTarget.
Scripts/FitMode/FitTargets.csSocketFitTarget, ItemFitTarget, BatFitTarget.
Scripts/FitMode/FitOverrides.csThe JSON overrides: load, merge, apply, record, save.
Scripts/Data/CharacterFitProfile.csProfile asset, SocketFit, SocketSide.
Scripts/Batting/FitMeasurer.csAutomatic fit.
Scripts/UI/CustomizeView.csFIT button, Ctrl+Shift+F, docking the panel.
Editor/FitProfileTools.csGenerate Fit Profile For Batter.

Gotchas

SOCKET does nothing for today's batters

Every batter in DefaultContent plays as a rigged bean, and rigged beans hang cosmetics from their own bones, not from the profile. SOCKET then shows “This body has no fit profile” and only ITEM (and BATS) work. SOCKET applies to the library human (TT_demo_male_B).

  • Resources/FitOverrides.json does not exist on main yet; the first Editor ITEM save on a code-built cosmetic creates it.
  • Ctrl+Shift+F works in release builds too: Fit Mode is hidden, not stripped.
  • Editor saves to assets made during Play mode stick after Play stops; that is the point.