|
|
- /************************************************************************************
-
- See SampleFramework license.txt for license terms. Unless required by applicable law
- or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied. See the license for specific
- language governing permissions and limitations under the license.
-
- ************************************************************************************/
-
- using System.Collections;
- using UnityEngine;
- using UnityEngine.Assertions;
-
- namespace OculusSampleFramework
- {
- public class TrainLocomotive : TrainCarBase
- {
- private const float MIN_SPEED = 0.2f;
- private const float MAX_SPEED = 2.7f;
- private const float SMOKE_SPEED_MULTIPLIER = 8f;
- private const int MAX_PARTICLES_MULTIPLIER = 3;
-
- private enum EngineSoundState
- {
- Start = 0,
- AccelerateOrSetProperSpeed,
- Stop
- };
-
- [SerializeField]
- [Range(MIN_SPEED, MAX_SPEED)]
- protected float _initialSpeed = 0f;
-
- [SerializeField] private GameObject _startStopButton = null;
- [SerializeField] private GameObject _decreaseSpeedButton = null;
- [SerializeField] private GameObject _increaseSpeedButton = null;
- [SerializeField] private GameObject _smokeButton = null;
- [SerializeField] private GameObject _whistleButton = null;
- [SerializeField] private GameObject _reverseButton = null;
- [SerializeField] private AudioSource _whistleAudioSource = null;
- [SerializeField] private AudioClip _whistleSound = null;
- [SerializeField] private AudioSource _engineAudioSource = null;
- [SerializeField] private AudioClip[] _accelerationSounds = null;
- [SerializeField] private AudioClip[] _decelerationSounds = null;
- [SerializeField] private AudioClip _startUpSound = null;
-
- [SerializeField] private AudioSource _smokeStackAudioSource = null;
- [SerializeField] private AudioClip _smokeSound = null;
-
- [SerializeField] private ParticleSystem _smoke1 = null;
- [SerializeField] private ParticleSystem _smoke2 = null;
- [SerializeField] private TrainCarBase[] _childCars = null;
-
- private bool _isMoving = true;
- private bool _reverse = false;
- private float _currentSpeed, _speedDiv;
-
- private float _standardRateOverTimeMultiplier;
- private int _standardMaxParticles;
-
- private Coroutine _startStopTrainCr;
-
- private void Start()
- {
- Assert.IsNotNull(_startStopButton);
- Assert.IsNotNull(_decreaseSpeedButton);
- Assert.IsNotNull(_increaseSpeedButton);
- Assert.IsNotNull(_smokeButton);
- Assert.IsNotNull(_whistleButton);
- Assert.IsNotNull(_reverseButton);
- Assert.IsNotNull(_whistleAudioSource);
- Assert.IsNotNull(_whistleSound);
- Assert.IsNotNull(_smoke1);
-
- Assert.IsNotNull(_engineAudioSource);
- Assert.IsNotNull(_accelerationSounds);
- Assert.IsNotNull(_decelerationSounds);
- Assert.IsNotNull(_startUpSound);
-
- Assert.IsNotNull(_smokeStackAudioSource);
- Assert.IsNotNull(_smokeSound);
-
-
- _standardRateOverTimeMultiplier = _smoke1.emission.rateOverTimeMultiplier;
- _standardMaxParticles = _smoke1.main.maxParticles;
-
- Distance = 0.0f;
- _speedDiv = (MAX_SPEED - MIN_SPEED) / _accelerationSounds.Length;
- _currentSpeed = _initialSpeed;
- UpdateCarPosition();
-
- _smoke1.Stop();
- _startStopTrainCr = StartCoroutine(StartStopTrain(true));
- }
-
- private void Update()
- {
- UpdatePosition();
- }
-
- public override void UpdatePosition()
- {
- if (!_isMoving)
- {
- return;
- }
-
- if (_trainTrack != null)
- {
- UpdateDistance();
- UpdateCarPosition();
- RotateCarWheels();
- }
-
- foreach (var trainCarBase in _childCars)
- {
- trainCarBase.UpdatePosition();
- }
- }
-
- public void StartStopStateChanged()
- {
- if (_startStopTrainCr == null)
- {
- _startStopTrainCr = StartCoroutine(StartStopTrain(!_isMoving));
- }
- }
-
- private IEnumerator StartStopTrain(bool startTrain)
- {
- float endSpeed = startTrain ? _initialSpeed : 0.0f;
-
- var timePeriodForSpeedChange = 3.0f;
- if (startTrain)
- {
- _smoke1.Play();
- _isMoving = true;
- var emissionModule1 = _smoke1.emission;
- var mainModule = _smoke1.main;
- emissionModule1.rateOverTimeMultiplier = _standardRateOverTimeMultiplier;
- mainModule.maxParticles = _standardMaxParticles;
- timePeriodForSpeedChange = PlayEngineSound(EngineSoundState.Start);
- }
- else
- {
- timePeriodForSpeedChange = PlayEngineSound(EngineSoundState.Stop);
- }
-
- // don't loop audio at first; only do when train continues movement below
- _engineAudioSource.loop = false;
-
- // make time period a tad shorter so that if it's not looping, we don't
- // catch the beginning of the sound
- timePeriodForSpeedChange = timePeriodForSpeedChange * 0.9f;
- float startTime = Time.time;
- float endTime = Time.time + timePeriodForSpeedChange;
- float startSpeed = _currentSpeed;
- while (Time.time < endTime)
- {
- float t = (Time.time - startTime) / timePeriodForSpeedChange;
- _currentSpeed = startSpeed * (1.0f - t) + endSpeed * t;
- UpdateSmokeEmissionBasedOnSpeed();
- yield return null;
- }
-
- _currentSpeed = endSpeed;
- _startStopTrainCr = null;
- _isMoving = startTrain;
- if (!_isMoving)
- {
- _smoke1.Stop();
- }
- else
- {
- _engineAudioSource.loop = true;
- PlayEngineSound(EngineSoundState.AccelerateOrSetProperSpeed);
- }
- }
-
- private float PlayEngineSound(EngineSoundState engineSoundState)
- {
- AudioClip audioClip = null;
-
- if (engineSoundState == EngineSoundState.Start)
- {
- audioClip = _startUpSound;
- }
- else
- {
- AudioClip[] audioClips = engineSoundState == EngineSoundState.AccelerateOrSetProperSpeed
- ? _accelerationSounds
- : _decelerationSounds;
- int numSounds = audioClips.Length;
- int speedIndex = (int)Mathf.Round((_currentSpeed - MIN_SPEED) / _speedDiv);
- audioClip = audioClips[Mathf.Clamp(speedIndex, 0, numSounds - 1)];
- }
-
- // if audio is already playing and we are playing the same track, don't interrupt it
- if (_engineAudioSource.clip == audioClip && _engineAudioSource.isPlaying &&
- engineSoundState == EngineSoundState.AccelerateOrSetProperSpeed)
- {
- return 0.0f;
- }
-
- _engineAudioSource.clip = audioClip;
- _engineAudioSource.timeSamples = 0;
- _engineAudioSource.Play();
-
- return audioClip.length;
- }
-
- private void UpdateDistance()
- {
- var signedSpeed = _reverse ? -_currentSpeed : _currentSpeed;
- Distance = (Distance + signedSpeed * Time.deltaTime) % _trainTrack.TrackLength;
- }
-
- public void DecreaseSpeedStateChanged()
- {
- if (_startStopTrainCr == null && _isMoving)
- {
- _currentSpeed = Mathf.Clamp(_currentSpeed - _speedDiv, MIN_SPEED, MAX_SPEED);
- UpdateSmokeEmissionBasedOnSpeed();
- PlayEngineSound(EngineSoundState.AccelerateOrSetProperSpeed);
- }
- }
-
- public void IncreaseSpeedStateChanged()
- {
- if (_startStopTrainCr == null && _isMoving)
- {
- _currentSpeed = Mathf.Clamp(_currentSpeed + _speedDiv, MIN_SPEED, MAX_SPEED);
- UpdateSmokeEmissionBasedOnSpeed();
- PlayEngineSound(EngineSoundState.AccelerateOrSetProperSpeed);
- }
- }
-
- private void UpdateSmokeEmissionBasedOnSpeed()
- {
- var emissionModule = _smoke1.emission;
- emissionModule.rateOverTimeMultiplier = GetCurrentSmokeEmission();
- var mainModule = _smoke1.main;
- mainModule.maxParticles = (int)Mathf.Lerp(_standardMaxParticles, _standardMaxParticles * MAX_PARTICLES_MULTIPLIER,
- _currentSpeed / (MAX_SPEED - MIN_SPEED));
- }
-
- private float GetCurrentSmokeEmission()
- {
- return Mathf.Lerp(_standardRateOverTimeMultiplier, _standardRateOverTimeMultiplier * SMOKE_SPEED_MULTIPLIER,
- _currentSpeed / (MAX_SPEED - MIN_SPEED));
- }
-
- public void SmokeButtonStateChanged()
- {
- if (_isMoving)
- {
- _smokeStackAudioSource.clip = _smokeSound;
- _smokeStackAudioSource.timeSamples = 0;
- _smokeStackAudioSource.Play();
-
- _smoke2.time = 0.0f;
- _smoke2.Play();
- }
- }
-
- public void WhistleButtonStateChanged()
- {
- if (_whistleSound != null)
- {
- _whistleAudioSource.clip = _whistleSound;
- _whistleAudioSource.timeSamples = 0;
- _whistleAudioSource.Play();
- }
- }
-
- public void ReverseButtonStateChanged()
- {
- _reverse = !_reverse;
- }
- }
- }
|