Characters and Rigs
In short
The at-bat talks to the batter through
IBatterFigureand to the pitcher throughIPitcherFigure. Two batter figures exist side by side:HumanBatter(an animated Humanoid, used by every batter today, with the rigged bean models) andBeanBatter(the code-built bean). Cosmetics hang on sockets (CosmeticAnchors) and are built byCosmeticBuilder.
How it works
Which batter figure stands in the box
AtBatController creates both figures at start (HumanBatter.Create and a BeanBatter). SelectFigure(batter) picks:
- Bean when there is no
HumanBatter(library missing or not Humanoid), orCharacterLibrary.useBeansis on, or the batter’smodelisBatterModel.Bean. - Human otherwise.
HumanBatter.SetBatterthen loads the batter’sriggedModel(for exampleCharacters/Peapod) and turns it into a Humanoid withBeanRig.MakeHumanoid. If that fails, or the batter has noriggedModel, it uses the library’sbatterPrefab.
In DefaultContent all four batters (Peapod, Baked Bean, String Bean, Pinto) are BatterModel.Human with a rigged bean model, so all of them play as animated rigged beans. useBeans is off in Resources/CharacterLibrary.asset.
HumanBatter
- Plays the batting-stance idle through a
PlayableGraph(no Animator Controller asset). InLateUpdatethe upper body leans and twists with the swing, the head turns to the pitcher, and two-bone IK puts both hands on the bat handle. - Before pitches it plays a walk-in (first pitch of a round) or a step-in, placed to end on the batter’s spot; the bat rides in the animated hands, then is handed back to the stance grip.
- Rigged beans keep their modelled size; the library human is scaled to
batterHeadHeight. - On a bean whose rig has both a chest and an upper chest (String Bean since #44), the swing’s twist and lean are shared up the spine (spine 0.3, chest 0.35, upper chest 0.35) and the head turn toward the pitcher is shared too (chest 0.2, upper chest 0.35, head 0.45 of the turn), so the long neck curves instead of hinging at the head and the waist doesn’t pinch. Other figures twist the spine and turn the head as before.
- A home run of 480 ft or more knocks the hat off (
CosmeticWardrobe.KnockOffHat).FlyingHattumbles it to the grass and flies it back on at the next pitch.
BeanRig
Maps a bean’s bone names to Unity Humanoid bones, by either of two namings: the bean rig from the Blender scripts (hips, spine, chest, head, upper_arm.L, forearm.L, hand.L, thigh.L, shin.L, foot.L and the .R side) or the game-engine style rig String Bean uses since #44 (pelvis, spine_01, spine_02, spine_03, head, clavicle_l, upperarm_l, lowerarm_l, hand_l, thigh_l, calf_l, foot_l and the _r side). Chest, upper chest and the shoulders are optional (shorter beans go hips, spine, head); any other missing bone logs a warning and the bean can’t be animated. It builds an avatar with a T-pose reference (the beans are modelled in an A-pose), so the same Mixamo-style clips play on them. It also places cosmetic sockets from the hat socket (hat_socket or SOCKET_Head), head and foot bones, using riggedEyeHeight and riggedEyeSpacing from the batter definition for glasses.
BeanBatter (code-built)
Built from primitives: a bean body in the batter’s colour (shape from BeanShape: Peapod, Baked, String, Pinto), big eyes, a grin, a jersey band, a default cap and shoes (hidden when cosmetics replace them), white gloves locked to the bat and rubber-hose arms solved with NoodleArm (two-bone IK that stretches when out of reach). Hops into the box, blinks, breathes. Used only when the conditions above pick it.
Pitchers
AtBatController uses HumanPitcher.Create(library) and falls back to BeanPitcher.Create.
HumanPitcher, clip mode (CharacterLibrary.pitchingClipset): plays the pitching clip, finds the release frame as the frame where the throwing hand moves fastest, turns the pitcher so that throw points at the plate, and times the clip so release lands on the pitch’s release time. Scripted mode (no clip): idle plus an IK delivery.BeanPitcher: scripted delivery with rubber-hose arms.- Either way,
ReleasePointcomes from the figure and pitches start there.
Staging for the end-of-game cutscenes
AtBatController.Outro.cs stages the figures for OutroDirector (Cutscenes): StageOutro puts a batter (yours, or a teammate’s batter, outfit and bat in co-op) in the box and the pitcher on the mound with no zone, ring or ball; OutroPose(relaxed) switches between the stance and standing without the bat; TopplePitcher(angle) knocks the pitcher over backwards, pivoting at his feet, while his animation keeps playing (BOSS DOWN); ShowReplayBall flies the winning hit’s ball along its recorded path. EndOutro undoes all of it.
Cosmetics on figures
CosmeticAnchor= a bone plus a bone-local pose and a size;CosmeticAnchorsholdsheadTop,eyes,leftFoot,rightFoot.- Where anchors come from: rigged beans from
BeanRig.Anchors; the library human from itsCharacterFitProfileif set, elseFitMeasurer(the automatic fit); the code bean from its shape. CosmeticWardrobebuilds items on the anchors, tears them down, remembers the hat, and draws sockets as gizmos.CosmeticBuilder.Buildmakes the code-built styles (TopHat, BallCap, CowboyHat, Sunglasses, NerdGlasses, Monocle, Sneakers, Cleats, ClownShoes) sized from the anchor, or instantiates the item’sprefab(Model). Bats never use a socket: they hang on the bat pivot.CosmeticPopgives a new item a scale bounce (0.5 to 1.12 to 1 in 0.22 s).
Libraries in Resources
| Asset | Holds |
|---|---|
Resources/CharacterLibrary.asset | useBeans (off), batter prefab TT_demo_male_B and pitcher prefab TT_demo_male_A (ToonyTinyPeople), the batter fit profile Content/Characters/TT_demo_male_B_Fit.asset, clips (BaseballIdle, BaseballWalkIn, BaseballStepIn, BaseballPitching, idle m_idle_A), head heights 1.1 / 1.2 m. |
Resources/BatModelLibrary.asset | Bat prefab per Bat-slot upgrade id, a default bat, and the alignment (modelRotation, modelOffset, modelScale). Missing = the primitive bat. |
Resources/Characters/ | The rigged beans: Peapod.fbx, BakedBean.fbx, StringBean.fbx, Pinto.fbx, and the textures peapod_albedo.png, baked_bean_albedo.png, pinto_gradient.png. String Bean has no texture since #44 (flat toon colours; riggedTexture is null). |
Blender scripts (Tools/Blender/)
Run with blender --background --factory-startup --python <script> -- <args>.
| Script | Makes |
|---|---|
make_bean.py <BeanName> <out_dir> [preview.png] | A rigged bean with the shared rig and bone names. Only Pinto is defined; Peapod and Baked Bean come from the team’s own scripts in a separate HomerunDerbyAssets repo. The new String Bean (#44) was modelled in a Blender file outside the repo (the DefaultContent comment says Documents/StringBean), with smoother neck and waist weights and a brighter green. |
make_farm_kit.py <out_dir> [lineup.png] | Farmyard props (Resources/Props/Farm). |
make_moon_kit.py <out_dir> [lineup.png] | Moon Stadium props (Resources/Props/Moon). Naming: _Spin, _Yaw, _Bob, materials with Glow. |
Numbers
| What | Value | Where to tune |
|---|---|---|
| Hat knock-off distance | 480 ft (both figures) | HumanBatter.HatFliesAtFt, BeanBatter.OnHitLanded |
| Bean head radius (sizing) | 0.13 m | BeanRig.HeadRadius |
| Bean foot length (sizing) | 0.28 m | BeanRig.FootLength |
| Default bat scale | 1.07 | BatModelLibrary.modelScale |
| String Bean eye height / spacing | 1.25 m / 0.109 m (were 1.52 / 0.128 with the old model) | DefaultContent (RiggedBean) |
| Long-spine twist shares | spine 0.3, chest 0.35, upper chest 0.35 | HumanBatter.SpineTwistShare etc. |
| Long-neck head-turn shares | chest 0.2, upper chest 0.35, head 0.45 | HumanBatter.ChestShare, UpperChestShare, HeadShare |
In the code
| File | What it does |
|---|---|
Scripts/Batting/IBatterFigure.cs | Batter contract, incl. the Fit Mode members (FitProfile, Anchors, GetBone, RefreshFit, TryMeasureFit). |
Scripts/Pitching/IPitcherFigure.cs | Pitcher contract (ReleasePoint, BallInHand, LeadTime, BeginPitch). |
Scripts/Batting/HumanBatter.cs | Humanoid batter. |
Scripts/Batting/BeanRig.cs | Rigged bean to Humanoid, either bone naming. |
Scripts/Batting/AtBatController.Outro.cs | Figures staged for the end-of-game cutscenes. |
Scripts/Batting/BeanBatter.cs | Code-built bean. |
Scripts/Core/HumanRig.cs | Spawn (and Toonify), PlayLoop, FitHeadHeight, SolveTwoBone, SolveStretchy. |
Scripts/Batting/NoodleArm.cs | Rubber-hose arm IK. |
Scripts/Pitching/HumanPitcher.cs, BeanPitcher.cs | Pitcher figures. |
Scripts/Batting/CosmeticBuilder.cs, CosmeticWardrobe.cs, CosmeticPop.cs, FlyingHat.cs | Cosmetics on figures. |
Scripts/Data/CharacterLibrary.cs, BatModelLibrary.cs | The Resources libraries. |
Gotchas
- The
CharacterFitProfileis tuned for the library human only. Rigged beans ignore it (_profile = null), so Fit Mode’s SOCKET mode says the body has no fit profile for every current batter (Fit Mode). BeanShapestill matters only whenuseBeansswaps everyone to code-built beans.- A batter’s
riggedModelthat fails to load logs a warning and falls back to the library human. BeanRig’s comment still points atHomerunDerbyAssets/scripts/make_peapod.pyfor the bean-rig naming; the String Bean model itself has no script in either repo.
Related
- Batters: the batter content
- Cosmetics: the cosmetic content
- Fit Mode: editing sockets and items
- Add a Batter and Add a Cosmetic
- Rendering:
Toonify