using UnityEngine; // Sci-Fi Ship Controller. Copyright (c) 2018-2023 SCSM Pty Ltd. All rights reserved. namespace SciFiShipController { /// /// Script to rotate a light on the y-axis. If an audiosource (and clip) is attached to the same /// gameobject, it will activate and deactivate at the same time as the light. /// If including an audiosource, turn off Play On Awake for the audiosource. /// Assumes original rotation y is between -359.999 and +359.999 /// [RequireComponent(typeof(Light))] public class BeaconLight : MonoBehaviour { #region Public Variables /// /// If enabled, the InitialiseBeacon() will be called as soon as Awake() runs. This should be disabled if you are /// instantiating the beacon through code. /// public bool initialiseOnAwake = false; // Turn on or off the beacon after initialisation at runtime, call TurnOn(..) public bool isOn = false; public float rotationsPerMinute = 30f; #endregion #region Private Variables private Light beacon = null; private AudioSource audioSource = null; private bool isInitialised = false; //private Quaternion rotation; //private float timer = 0f; private float currentRotationAngle = 0f; private float originalRotationAngle = 0f; private float fadeAudioTimer = 0f; private float fadeAudioDuration = 1f; private float fadeAudioStartVolume = 1f; private AnimationCurve audioFadeOutCurve; #endregion #region Initialisation Methods private void Awake() { beacon = GetComponent(); if (beacon == null) { #if UNITY_EDITOR Debug.LogWarning("BeaconLight on " + this.name + " could not find an attached Light component"); #endif } else { if (initialiseOnAwake) { InitialiseBeacon(); } else { beacon.enabled = false; } } } /// /// Initialise the beacon and get ready to rotate the beacon /// public void InitialiseBeacon() { if (beacon != null) { beacon.enabled = isOn; // Get the original positive rotation angle originalRotationAngle = transform.rotation.eulerAngles.y; if (originalRotationAngle < 360f) { originalRotationAngle += 360f; } currentRotationAngle = originalRotationAngle; audioSource = GetComponent(); if (audioSource != null && audioSource.clip != null && audioSource.isActiveAndEnabled) { if (isOn) { if (!audioSource.isPlaying) { audioSource.Play(); } } else if (audioSource.isPlaying) { audioSource.Stop(); } } audioFadeOutCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); isInitialised = true; } } #endregion #region Update Methods // Update is called once per frame void Update() { if (isInitialised && isOn) { // Based on the rotation speed, how far has the beacon rotated in the last frame? // Need to use per frame rotation because rotation speed may have changed float rotThisFrame = rotationsPerMinute / 60f * Time.deltaTime; // Discard the integral value rotThisFrame -= (float)System.Math.Floor(rotThisFrame); currentRotationAngle += rotThisFrame * 360f; if (currentRotationAngle >= 360f) { currentRotationAngle -= 360f; } transform.rotation = Quaternion.Euler(0f, currentRotationAngle, 0f); if (fadeAudioTimer > 0f) { fadeAudioTimer -= Time.deltaTime; if (fadeAudioTimer > 0f) { audioSource.volume = audioFadeOutCurve.Evaluate(1f - (fadeAudioTimer / fadeAudioDuration)); } else if (audioSource != null && audioSource.clip != null && audioSource.isActiveAndEnabled && audioSource.isPlaying) { audioSource.Stop(); } } } } #endregion #region Public Methods /// /// While the beacon light is still on, fade out the audio /// /// Duration in seconds public void FadeOutAudio (float fadeDuration) { if (isInitialised && audioSource != null && audioSource.clip != null && audioSource.isActiveAndEnabled && audioSource.isPlaying) { fadeAudioDuration = fadeDuration; fadeAudioTimer = fadeDuration; fadeAudioStartVolume = audioSource.volume; } } /// /// Turn on (or off) the beacon /// /// public void TurnOn(bool turnOn) { if (isInitialised && beacon != null) { isOn = turnOn; bool isValidAudioClip = audioSource != null && audioSource.clip != null && audioSource.isActiveAndEnabled; // If required , turn off audio before light (should all be done in the same frame... but just incase) if (isValidAudioClip && !isOn && audioSource.isPlaying) { audioSource.Stop(); } beacon.enabled = turnOn; // If required, turn on audio after light if (isValidAudioClip && isOn && !audioSource.isPlaying) { audioSource.Play(); } // Reset rotation currentRotationAngle = originalRotationAngle; fadeAudioTimer = 0f; } } #endregion } }