Ballpark Building
In short
Every park is built from its
BallparkDefinitionbyBallparkBuilder.Build, all in code. Only the props around the field (barns, rocks) can come from a prefab; the field, wall, targets and stands always stay in code because the ball physics and scoring read the same numbers.
How it works
Build order
BallparkBuilder.Build(park) returns at once if park is already built. Otherwise it destroys the old park root and builds, under a new root named after the park:
- Ground by
GroundStyle:Mowed(striped grass, dirt diamond, infield grass, mound, plate, then a warning track),Sandlot(patchy grass, one big dirt infield with bases, no warning track),Lunar(cratered dust, a dark regolith field, landing pad at the plate, then a warning track). - Foul lines.
- Wall by
WallStyle:Paddedwall, orWoodFence(post-and-rail, more fencing down the foul lines). - Targets: a flat coloured disc per ground target; aerial targets get no disc (their prop is the marker). Inside a stadium, a 12 m pole marks each target that is not
outsideStadium. - If
park.stadium:StadiumCrowd(stands and fans, kept inBallparkBuilder.Crowd; null for parks without stands) and light towers. - Sky extras: 260 stars for Night and Space skies; the Earth over Space parks.
StadiumAmbience: flags streaming downwind, clouds drifting with the wind, gulls on day games.Scoreboard(Scoreboard), kept inBallparkBuilder.Board.ParkDressing.Build: the props.- Lighting and
SkyBuilder.Apply(Rendering).
Stands (StadiumLayout + StadiumCrowd)
StadiumLayoutis shared by the builder andHitPhysics, so the seats you see are the seats the ball bounces off. Two kinds of stepped stands: outfield bleachers following the wall behind a lawn, and grandstands along each foul line. Each step is a solid block (a floor and a riser).- The lawn between wall and bleachers is at least 30 ft, and always deep enough to leave every in-stadium target open (target edge + 15 ft).
StadiumCrowddraws a GPU-instanced crowd in batches of 1023. Fans bob, stand when the ball is hit, erupt on home runs (most near where it lands), scramble when a ball lands in their seats, sit on outs, and do the wave every 25 to 45 s when quiet. Density and seat colour come from the park (crowdDensity,seatColor).- For the cutscenes (Cutscenes),
StadiumCrowd.Celebrate(seconds)puts every fan on their feet, arms up and bouncing;Slump(seconds)sinks them into their seats with no wave;Calm()returns to following the game.OutroDirectorreaches them throughBallparkBuilder.Crowd.
Light towers
Four towers (two behind the outfield at +-30 deg, one beside each foul line). At night the lamps glow (unlit HDR colour for bloom) and each tower adds a spotlight aimed at the infield, its intensity set from the distance so each adds about the same light where the action is.
Park dressing (props)
ParkDressing.Build picks, in order:
- The park’s hand-placed prefab:
Resources.Load(park.dressing)(for exampleParks/farm_Dressing). - Else the code layout from
ParkLayouts(onlyfarmandmoonhave one).
Then it strips colliders (props are visual only), Toonifys everything, makes *Glow* materials unlit and HDR-bright (big glowing parts also get a point light), and animates children by name: _Spin (turns about its flattest axis), _Yaw (pans slowly), _Bob (drifts up and down).
ParkLayouts places props from Resources/Props/Farm/ and Resources/Props/Moon/ relative to the park’s wall, foul lines and targets, so they follow any retuning. It uses a fixed System.Random seed (1717 for the farm) so the layout is the same every time. The moon’s Meteor Shower bonus gets a MeteorShower (meteors streaking through the zone; purely visual, the scoring zone is an aerial target).
Fireworks
Fireworks (in Scripts/Ballparks/, but added to [Game] by OutroDirector, not built with the park) draws the end-of-game fireworks: shells climb from behind the outfield wall and burst into spheres of HDR sparks that drift down under light gravity and drag. No particle systems or assets: instanced unlit spheres, one batch per colour. Flash lets the post-processing pulse with each burst (Rendering); Puff makes small low bursts (dust off the mound when a boss falls, confetti). Clear() removes everything when the scene ends.
Hand-arranging dressing
- Tools > Home Run Derby > Bake Park Dressing turns each park’s code layout into
Assets/_Project/Resources/<park.dressing>.prefab, keeping prefab links to the props. It asks before replacing an existing prefab. - Open the prefab. The
ParkDressinginspector (ParkDressingEditor) has a Park picker and “View from batter camera” / “View field from above”; the Scene view draws foul lines, the wall, target circles, the stands footprint and the batter camera’s view. - Move, add and delete props. The prefab now wins over the code layout at runtime.
Numbers
| What | Value | Where to tune |
|---|---|---|
| Ground size (mowed) | 400 m, centred 80 m out | BallparkBuilder.GroundSizeM, GroundCenterZ |
| Lunar ground | 1100 m, centred 150 m out | LunarGroundSizeM, LunarGroundCenterZ |
| Warning track | 15 ft | WarningTrackFt |
| Light tower height | 38 m | TowerHeightM |
| Outfield bleachers | 12 rows, 1.6 m deep, 1 m rise | StadiumLayout.Rows, RowDepth, RowRise |
| Foul grandstands | 9 rows, 1.4 m deep, 0.9 m rise, 10 m from the line, from 28 m | StadiumLayout.Foul* |
| Min lawn behind the wall | 30 ft | StadiumLayout.MinGapFt |
| Fan scale | 1.5 | StadiumCrowd.FanScale |
| Flags fully out at | 15 mph | StadiumAmbience.StrongWindMph |
| Clouds / birds | 10 / 6 | StadiumAmbience |
| Fireworks: sparks / shell climb / spark gravity / drag / glow | 2400 max / 1.15 s / 3.2 / 1.6 / x 3.2 HDR | Fireworks.MaxSparks, ShellSeconds, SparkGravity, SparkDrag, Glow |
In the code
| File | What it does |
|---|---|
Scripts/Ballparks/BallparkBuilder.cs | Init, Build, ground, walls, targets, towers, sky extras, ApplyLighting. |
Scripts/Ballparks/StadiumLayout.cs | Stand geometry; SurfaceHeight for physics and shards. |
Scripts/Ballparks/StadiumCrowd.cs | Stands and the instanced crowd; Celebrate, Slump, Calm. |
Scripts/Ballparks/Fireworks.cs | Code-built fireworks for the outros. |
Scripts/Ballparks/StadiumAmbience.cs | Flags, clouds, gulls. |
Scripts/Ballparks/ParkDressing.cs | Props: load, toonify, glow, animate; Scene-view field gizmos. |
Scripts/Ballparks/ParkLayouts.cs | Code layouts for farm and moon. |
Scripts/Ballparks/MeteorShower.cs | The moon’s meteors. |
Scripts/Ballparks/ParkTextures.cs | Ground textures. |
Scripts/Ballparks/BallparkMath.cs | Feet/metres and field coordinates: plate at origin, +Z to center field, spray -45 = left line. |
Editor/ParkDressingTools.cs | ParkDressingEditor and Bake Park Dressing. |
Gotchas
- No
Resources/Parks/*_Dressing.prefabis in the repo on main, so the farm and the moon use their code layouts. Buildskips a park that is already built. A run is one park, so the park (and anything on it, like scoreboard holes) persists from inning to inning.- Props never collide with the ball. Only the field, wall, stands and scoreboard are physical, and those are in code.
- Kit models face -Y in Blender, which is +Z in Unity;
ParkLayouts.FaceHometurns them to home plate.
Related
- Ballparks: the park content
- Cutscenes: what drives the crowd, scoreboard and fireworks at the end of a game
- Hit Physics: what reads the wall and stands
- Rendering: sky, toon shader, ground textures
- Scoreboard: the breakable board
- Add a Map and Add a Ballpark Modifier