1 using System;
2 using
UnityEngine;
3 using
Random = UnityEngine.Random;
4
5 namespace
UnityStandardAssets.Vehicles.Car
6 {
7     
[RequireComponent(typeof (CarController))]
8     
public class CarAudio : MonoBehaviour
9     {
10         
// This script reads some of the car's current properties and plays sounds accordingly.
11         
// The engine sound can be a simple single clip which is looped and pitched, or it
12         
// can be a crossfaded blend of four clips which represent the timbre of the engine
13         
// at different RPM and Throttle state.
14
15         
// the engine clips should all be a steady pitch, not rising or falling.
16
17         
// when using four channel engine crossfading, the four clips should be:
18         
// lowAccelClip : The engine at low revs, with throttle open (i.e. begining acceleration at very low speed)
19         
// highAccelClip : Thenengine at high revs, with throttle open (i.e. accelerating, but almost at max speed)
20         
// lowDecelClip : The engine at low revs, with throttle at minimum (i.e. idling or engine-braking at very low speed)
21         
// highDecelClip : Thenengine at high revs, with throttle at minimum (i.e. engine-braking at very high speed)
22
23         
// For proper crossfading, the clips pitches should all match, with an octave offset between low and high.
24
25
26         
public enum EngineAudioOptions // Options for the engine audio
27         {
28             Simple,
// Simple style audio
29             FourChannel
// four Channel audio
30         }
31
32         
public EngineAudioOptions engineSoundStyle = EngineAudioOptions.FourChannel;// Set the default audio options to be four channel
33         
public AudioClip lowAccelClip; // Audio clip for low acceleration
34         
public AudioClip lowDecelClip; // Audio clip for low deceleration
35         
public AudioClip highAccelClip; // Audio clip for high acceleration
36         
public AudioClip highDecelClip; // Audio clip for high deceleration
37         
public float pitchMultiplier = 1f; // Used for altering the pitch of audio clips
38         
public float lowPitchMin = 1f; // The lowest possible pitch for the low sounds
39         
public float lowPitchMax = 6f; // The highest possible pitch for the low sounds
40         
public float highPitchMultiplier = 0.25f; // Used for altering the pitch of high sounds
41         
public float maxRolloffDistance = 500; // The maximum distance where rollof starts to take place
42         
public float dopplerLevel = 1; // The mount of doppler effect used in the audio
43         
public bool useDoppler = true; // Toggle for using doppler
44
45         
private AudioSource m_LowAccel; // Source for the low acceleration sounds
46         
private AudioSource m_LowDecel; // Source for the low deceleration sounds
47         
private AudioSource m_HighAccel; // Source for the high acceleration sounds
48         
private AudioSource m_HighDecel; // Source for the high deceleration sounds
49         
private bool m_StartedSound; // flag for knowing if we have started sounds
50         
private CarController m_CarController; // Reference to car we are controlling
51
52
53         
private void StartSound()
54         {
55             
// get the carcontroller ( this will not be null as we have require component)
56             m_CarController = GetComponent<CarController>();
57
58             
// setup the simple audio source
59             m_HighAccel = SetUpEngineAudioSource(highAccelClip);
60
61             
// if we have four channel audio setup the four audio sources
62             
if (engineSoundStyle == EngineAudioOptions.FourChannel)
63             {
64                 m_LowAccel = SetUpEngineAudioSource(lowAccelClip);
65                 m_LowDecel = SetUpEngineAudioSource(lowDecelClip);
66                 m_HighDecel = SetUpEngineAudioSource(highDecelClip);
67             }
68
69             
// flag that we have started the sounds playing
70             m_StartedSound =
true;
71         }
72
73
74         
private void StopSound()
75         {
76             
//Destroy all audio sources on this object:
77             
foreach (var source in GetComponents<AudioSource>())
78             {
79                 Destroy(source);
80             }
81
82             m_StartedSound =
false;
83         }
84
85
86         
// Update is called once per frame
87         
private void Update()
88         {
89             
// get the distance to main camera
90             
float camDist = (Camera.main.transform.position - transform.position).sqrMagnitude;
91
92             
// stop sound if the object is beyond the maximum roll off distance
93             
if (m_StartedSound && camDist > maxRolloffDistance*maxRolloffDistance)
94             {
95                 StopSound();
96             }
97
98             
// start the sound if not playing and it is nearer than the maximum distance
99             
if (!m_StartedSound && camDist < maxRolloffDistance*maxRolloffDistance)
100             {
101                 StartSound();
102             }
103
104             
if (m_StartedSound)
105             {
106                 
// The pitch is interpolated between the min and max values, according to the car's revs.
107                 
float pitch = ULerp(lowPitchMin, lowPitchMax, m_CarController.Revs);
108
109                 
// clamp to minimum pitch (note, not clamped to max for high revs while burning out)
110                 pitch = Mathf.Min(lowPitchMax, pitch);
111
112                 
if (engineSoundStyle == EngineAudioOptions.Simple)
113                 {
114                     
// for 1 channel engine sound, it's oh so simple:
115                     m_HighAccel.pitch = pitch*pitchMultiplier*highPitchMultiplier;
116                     m_HighAccel.dopplerLevel = useDoppler ? dopplerLevel :
0;
117                     m_HighAccel.volume =
1;
118                 }
119                 
else
120                 {
121                     
// for 4 channel engine sound, it's a little more complex:
122
123                     
// adjust the pitches based on the multipliers
124                     m_LowAccel.pitch = pitch*pitchMultiplier;
125                     m_LowDecel.pitch = pitch*pitchMultiplier;
126                     m_HighAccel.pitch = pitch*highPitchMultiplier*pitchMultiplier;
127                     m_HighDecel.pitch = pitch*highPitchMultiplier*pitchMultiplier;
128
129                     
// get values for fading the sounds based on the acceleration
130                     
float accFade = Mathf.Abs(m_CarController.AccelInput);
131                     
float decFade = 1 - accFade;
132
133                     
// get the high fade value based on the cars revs
134                     
float highFade = Mathf.InverseLerp(0.2f, 0.8f, m_CarController.Revs);
135                     
float lowFade = 1 - highFade;
136
137                     
// adjust the values to be more realistic
138                     highFade =
1 - ((1 - highFade)*(1 - highFade));
139                     lowFade =
1 - ((1 - lowFade)*(1 - lowFade));
140                     accFade =
1 - ((1 - accFade)*(1 - accFade));
141                     decFade =
1 - ((1 - decFade)*(1 - decFade));
142
143                     
// adjust the source volumes based on the fade values
144                     m_LowAccel.volume = lowFade*accFade;
145                     m_LowDecel.volume = lowFade*decFade;
146                     m_HighAccel.volume = highFade*accFade;
147                     m_HighDecel.volume = highFade*decFade;
148
149                     
// adjust the doppler levels
150                     m_HighAccel.dopplerLevel = useDoppler ? dopplerLevel :
0;
151                     m_LowAccel.dopplerLevel = useDoppler ? dopplerLevel :
0;
152                     m_HighDecel.dopplerLevel = useDoppler ? dopplerLevel :
0;
153                     m_LowDecel.dopplerLevel = useDoppler ? dopplerLevel :
0;
154                 }
155             }
156         }
157
158
159         
// sets up and adds new audio source to the gane object
160         
private AudioSource SetUpEngineAudioSource(AudioClip clip)
161         {
162             
// create the new audio source component on the game object and set up its properties
163             AudioSource source = gameObject.AddComponent<AudioSource>();
164             source.clip = clip;
165             source.volume =
0;
166             source.loop =
true;
167
168             
// start the clip from a random point
169             source.time = Random.Range(
0f, clip.length);
170             source.Play();
171             source.minDistance =
5;
172             source.maxDistance = maxRolloffDistance;
173             source.dopplerLevel =
0;
174             
return source;
175         }
176
177
178         
// unclamped versions of Lerp and Inverse Lerp, to allow value to exceed the from-to range
179         
private static float ULerp(float from, float to, float value)
180         {
181             
return (1.0f - value)*from + value*to;
182         }
183     }
184 }