Pitch-to-Steering mapping voice input to lateral movement
The core mechanic translates the player's vocal pitch into a steering value between -1 and 1. A low hum pushes the car to the left, a high note pushes it to the right, and silence lets the car drift straight. To keep the mapping feel natural across different singers, the incoming pitch is normalized against a calibrated neutral range captured at the start of the race, then smoothed with a small buffer so micro-fluctuations in the voice don't cause jitter on the car.
1/// Converts a raw pitch reading (Hz) into a normalized steering value in [-1, 1].
2/// neutralPitch is captured during the pre-race calibration.
3public float GetSteeringFromPitch(float rawPitch)
4{
5 if (rawPitch <= 0f) return 0f; // silence or unvoiced frame
6
7 float deviation = (rawPitch - neutralPitch) / pitchRange;
8 float steer = Mathf.Clamp(deviation, -1f, 1f);
9
10 // Smooth across a short ring buffer to hide vibrato / noise.
11 pitchBuffer[bufferIndex] = steer;
12 bufferIndex = (bufferIndex + 1) % pitchBuffer.Length;
13
14 float sum = 0f;
15 for (int i = 0; i < pitchBuffer.Length; i++) sum += pitchBuffer[i];
16 return sum / pitchBuffer.Length;
17}Breath & Turbo Rings rewarding sustained voicing
Turbo rings scattered along the track give the player a speed boost, but only if the car passes through them while the player is actively voicing. This made breath control a real strategic layer players have to decide when to save their breath for a ring versus when to keep steering through a twisty section. The ring uses a trigger collider plus a check against the voice controller's IsVoicing flag to decide whether to apply the boost.
1private void OnTriggerEnter(Collider other)
2{
3 var car = other.GetComponent<VoiceCar>();
4 if (car == null) return;
5
6 if (car.Voice.IsVoicing)
7 {
8 car.ApplyBoost(boostForce, boostDuration);
9 PlayRingHitEffect(success: true);
10 }
11 else
12 {
13 PlayRingHitEffect(success: false);
14 }
15}Two-Player Input Routing
Because both players share a single machine, each microphone is bound to its own voice channel at startup and piped into a dedicated VoiceController instance. The race manager holds references to both controllers and feeds them into the matching car, keeping the gameplay logic unaware of which physical mic is which it only sees "player 1 voice" and "player 2 voice."
