Swing and Timing
In short
The mouse aims, Space / click swings, and A/D, W/S held at contact aim the hit. The swing starts at the exact moment the button went down, so timing doesn’t depend on frame rate. Contact is real geometry: the simulated bat must pass within the hit radius (reach) of the ball. What the contact is worth (zone, grade, direction, launch) is in Batting Explained; what the player is told is in Batting Feedback.
How it works
Input (SwingInput)
- Swing press: Space, left mouse button or gamepad A, through the Input System.
PressTimeis when the button really went down, moved back at most one frame. The oldInputclass is a fallback if the Input System is off. - Aim: the mouse ray hits the plate plane. The aim point is clamped to x -0.7 to 0.7 m, y 0.1 to 1.6 m. The AIM SPEED setting scales mouse movement around the zone’s centre.
- Hit aim (
ReadHitAim, read at the moment of contact): A / left arrow = -1 x (left field), D / right arrow = +1 x (right field), W / up arrow = +1 y (higher), S / down arrow = -1 y (lower). The gamepad left stick adds its tilt beyond a 0.3 deadzone. Each axis is clamped to -1..1.
The aim helper (AimBat)
It replaced the aim ring in PR #46. Only the ends of a bat’s barrel are drawn: two rounded corners at the tip (right) and a short curve above and below where the barrel tapers into the handle (left). The sweet spot (0.6 m from the knob) is the gap between them, placed on the aim. The barrel’s half-height is 0.35 x reach, clamped to 0.04 to 0.1 m, so it grows with the Contact and Timing Window stats. The lines are warm gold over a dark ink edge, over a glow that breathes every 2.4 s. It hides during the match intro’s walk-up shot. A spectator sees the batter’s own reach.
The bat
BatSwingis the swing as a pure function of time since the press: load, through the zone, follow-through, in 0.2 s. The barrel points at the aim point 60% of the way through.- The hands follow the aim (
HandsFor: they step toward outside pitches).BatJigglesimulates the bat held from the knob chasing the pose, so the drawn bat wobbles. The simulated bat is the one that hits the ball. BatCollision.Sweepchecks the bat segment (0.12 m to 0.86 m from the knob) against the ball at 12 sub-steps per frame, so a fast ball can’t pass through. Contact is possible from the press until 0.28 s later.
From contact to a hit
SwingResolver.FromContact reads the contact: where along the bat (the zone and grade), the bat face’s direction (spray: early pulls, late pushes) and the ball’s height on the bat (under). Then it adds the held aim, rolls the launch and computes exit velocity and curve. All of it: Batting Explained.
A whiff gets a timing offset from when the barrel would have crossed the aim point: swingStart + 0.12 - ArrivalTime. A take has no numbers.
Hit radius (reach)
HitRadius = (0.037 + 0.033 + 0.12 x Contact) x sqrt(max(0.1, TimingWindow / 0.11)). With base stats this is 0.19 m. Contact adds reach and also widens the contact zones. Timing Window scales the reach only. See Stats.
Timing ring (optional assist)
The TIMING RING setting (off by default) shows a ring centred where the pitch will cross the plate. It shrinks from 0.4 m to the drawn ball’s size at the best moment to press. Colour says how pressing now would go: white = too early, yellow = contact, green = GREEN (a bolder ring, a second halo ring and a pop, so it isn’t colour-only). After you swing it freezes in that colour for 0.35 s.
TimingWindowScanner finds the windows by test-swinging the real bat code and grading each press with SwingResolver.Classify (the zone and timing part of a hit, with no random rolls), so a green ring always means a green swing. The ring closes on the middle of the green window, or else on the best press (best timed first, then squarest contact). Colours follow the at-bat’s own aim, AIM SPEED included. See GREEN Swings.
Numbers
| What | Value | Where to tune |
|---|---|---|
| Swing duration | 0.2 s | BatSwing.Seconds |
| Contact grace after the swing | 0.08 s | BatSwing.ContactGrace |
| Bat length / hittable from / sweet spot | 0.86 m / 0.12 m / 0.6 m from knob | BatSwing |
| Barrel radius / ball radius | 0.033 m / 0.037 m | BatSwing |
| Forgiveness per point of Contact | 0.12 m | SwingResolver.Forgiveness |
| Base timing window | 0.11 | SwingResolver.BaseTimingWindow, StatInfo.BaseValue |
| Full mistime at spray | 45 degrees | SwingResolver.PerfectSprayRange |
| Max spray | +/-80 degrees | SwingResolver.MaxSpray |
| Collision sub-steps | 12 per frame | BatCollision.SubSteps |
| Aim clamp | x +/-0.7 m, y 0.1 to 1.6 m | SwingInput.ReadAim |
| Stick deadzone (hit aim) | 0.3 | SwingInput.StickDeadzone |
| AIM SPEED range | 0.5x to 2.5x, steps of 0.05 | SettingsView |
| Aim helper barrel half-height | 0.35 x reach, 0.04 to 0.1 m | AimBat.ReachToBarrel, MinBarrel, MaxBarrel |
| Ring start radius / freeze | 0.4 m / 0.35 s | TimingIndicator |
| Ball drawn size | 1.35x its real size (physics unchanged) | BallSpin.VisualScale |
In the code
| File | What it does |
|---|---|
Assets/_Project/Scripts/Batting/SwingInput.cs | SwingPressed(), PressTime, ReadAim(), ReadHitAim() |
Assets/_Project/Scripts/Batting/SwingResolver.cs | HitRadius, Classify, FromContact, Whiff, Take, EarnsReplay, DevHomeRun |
Assets/_Project/Scripts/Batting/BatSwing.cs | Bat shape and swing motion over time, CanHit |
Assets/_Project/Scripts/Batting/BatCollision.cs | Sweep, BatContact, BatPose |
Assets/_Project/Scripts/Batting/BatJiggle.cs | The wobbling bat simulation |
Assets/_Project/Scripts/Batting/AimBat.cs | The aim helper |
Assets/_Project/Scripts/UI/TimingIndicator.cs | The timing ring |
Assets/_Project/Scripts/UI/TimingWindowScanner.cs | Finds the ring’s windows by test-swinging |
Gotchas
- “Timing” in grading is read from the direction the bat face sent the ball, not from a clock. A ball hit straight up the middle is perfect timing by definition.
- Timing sets direction only. The grade comes from where on the bat. See Batting Explained.
- The
StatTypecomments are stale:Contactadds 0.12 m of reach per point and sizes the zones (it does not multiply a radius around the aim), andTimingWindowis not seconds. The stat screen still shows Timing Window as “110 ms”. - The
SwingInputcomment mentions a “~40 ms green window”;SwingResolversays about 14 ms at the currentGreenTiming. - A gamepad can swing and aim the hit (stick) but cannot move the aim helper; that is mouse only.
- README line “mouse = aim the contact ring” is out of date: there is no ring any more, it’s the aim helper.
Related
- Batting Explained: zones, direction, launch, the held aim
- Batting Feedback: what the player sees and hears
- GREEN Swings: the top grade and its window
- Hit Physics: the flight that follows
- Pitching: the path the bat has to meet
- Controls: every input
- Stats: Power, Contact, Timing Window, Launch Angle