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.
| Mode | Target class | Edits | Sliders | Size range |
|---|---|---|---|---|
| SOCKET (hat, glasses, shoes) | SocketFitTarget | The 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, TURN | 0.05 to 1.2 m |
| ITEM | ItemFitTarget | The selected item’s own offset, rotation, scale. | absolute UP, FORWARD, SIDEWAYS, SCALE, TIP FWD, TURN | 0.3x to 3x |
| SOCKET in BATS | BatFitTarget | BatModelLibrary.modelOffset, modelRotation, modelScale for every bat model. | UP, SIDEWAYS, ALONG BAT, SCALE, TIP UP, TURN | 0.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
| Target | In the Editor | In a build |
|---|---|---|
| Socket | The CharacterFitProfile asset (SetDirty + SaveAssets) | persistentDataPath/fit-overrides.json |
| Item that is a real asset | That CosmeticDefinition asset | fit-overrides.json |
Item built in code (DefaultContent) | Assets/_Project/Resources/FitOverrides.json (committed) | fit-overrides.json |
| Bats | The BatModelLibrary asset | fit-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, andSocketFitentries (slot, side Center / Left / Right, Humanoid bone, bone-local position and euler, size).ToAnchors(animator)turns it intoCosmeticAnchors. Itsversionbumps on every edit so a running batter re-hangs cosmetics.FitMeasurer.Measureis 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 theCharacterLibrary.batterPrefabin the stance idle, measures it, and writesAssets/_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
| What | Value | Where to tune |
|---|---|---|
| Panel width | 300 | FitModeView.PanelWidth |
| Nudge range | +-0.25 m | FitModeView.NudgeRange |
| Tilt range | +-60 deg | FitModeView.TiltRange |
| Note shown for | 2.5 s | FlashSeconds |
| Camera distance while fitting | 0.9 (bats 1.7) | CustomizeView.FitFrameDistance, FitFrameDistanceBat |
In the code
| File | What it does |
|---|---|
Scripts/FitMode/FitModeView.cs | The panel, retargeting, the socket ring. |
Scripts/FitMode/IFitTarget.cs | FitValues, IFitTarget. |
Scripts/FitMode/FitTargets.cs | SocketFitTarget, ItemFitTarget, BatFitTarget. |
Scripts/FitMode/FitOverrides.cs | The JSON overrides: load, merge, apply, record, save. |
Scripts/Data/CharacterFitProfile.cs | Profile asset, SocketFit, SocketSide. |
Scripts/Batting/FitMeasurer.cs | Automatic fit. |
Scripts/UI/CustomizeView.cs | FIT button, Ctrl+Shift+F, docking the panel. |
Editor/FitProfileTools.cs | Generate Fit Profile For Batter. |
Gotchas
SOCKET does nothing for today's batters
Every batter in
DefaultContentplays 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.jsondoes 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.
Related
- Characters and Rigs: anchors, wardrobes and figures
- Cosmetics: the items being fitted
- Customization: the screen Fit Mode docks on
- Dev Menu and Shortcuts: every hidden key
- Save System: fit-overrides.json among the save files