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. PressTime is when the button really went down, moved back at most one frame. The old Input class 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

  • BatSwing is 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). BatJiggle simulates 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.Sweep checks 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

WhatValueWhere to tune
Swing duration0.2 sBatSwing.Seconds
Contact grace after the swing0.08 sBatSwing.ContactGrace
Bat length / hittable from / sweet spot0.86 m / 0.12 m / 0.6 m from knobBatSwing
Barrel radius / ball radius0.033 m / 0.037 mBatSwing
Forgiveness per point of Contact0.12 mSwingResolver.Forgiveness
Base timing window0.11SwingResolver.BaseTimingWindow, StatInfo.BaseValue
Full mistime at spray45 degreesSwingResolver.PerfectSprayRange
Max spray+/-80 degreesSwingResolver.MaxSpray
Collision sub-steps12 per frameBatCollision.SubSteps
Aim clampx +/-0.7 m, y 0.1 to 1.6 mSwingInput.ReadAim
Stick deadzone (hit aim)0.3SwingInput.StickDeadzone
AIM SPEED range0.5x to 2.5x, steps of 0.05SettingsView
Aim helper barrel half-height0.35 x reach, 0.04 to 0.1 mAimBat.ReachToBarrel, MinBarrel, MaxBarrel
Ring start radius / freeze0.4 m / 0.35 sTimingIndicator
Ball drawn size1.35x its real size (physics unchanged)BallSpin.VisualScale

In the code

FileWhat it does
Assets/_Project/Scripts/Batting/SwingInput.csSwingPressed(), PressTime, ReadAim(), ReadHitAim()
Assets/_Project/Scripts/Batting/SwingResolver.csHitRadius, Classify, FromContact, Whiff, Take, EarnsReplay, DevHomeRun
Assets/_Project/Scripts/Batting/BatSwing.csBat shape and swing motion over time, CanHit
Assets/_Project/Scripts/Batting/BatCollision.csSweep, BatContact, BatPose
Assets/_Project/Scripts/Batting/BatJiggle.csThe wobbling bat simulation
Assets/_Project/Scripts/Batting/AimBat.csThe aim helper
Assets/_Project/Scripts/UI/TimingIndicator.csThe timing ring
Assets/_Project/Scripts/UI/TimingWindowScanner.csFinds 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 StatType comments are stale: Contact adds 0.12 m of reach per point and sizes the zones (it does not multiply a radius around the aim), and TimingWindow is not seconds. The stat screen still shows Timing Window as “110 ms”.
  • The SwingInput comment mentions a “~40 ms green window”; SwingResolver says about 14 ms at the current GreenTiming.
  • 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.