301 lines
11 KiB
C#
301 lines
11 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
[System.Serializable]
|
||
public class FlickeringLightData
|
||
{
|
||
public Light light;
|
||
public float maxIntensity;
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class FlickeringRendererData
|
||
{
|
||
public Renderer renderer;
|
||
[Range(0f, 10f)]
|
||
public float flickerFactorMin = 1.2f;
|
||
|
||
[Range(0f, 10f)]
|
||
public float flickerFactorMax = 0.8f;
|
||
}
|
||
|
||
[RequireComponent(typeof(AudioSource))]
|
||
public class LightAnimationUpdate : MonoBehaviour
|
||
{
|
||
AudioSource lightFlickerAudioSource;
|
||
//AudioClip lightFlickerAudioClip;
|
||
AudioClip lightFlickerAudioClipForThisObject;
|
||
Animator _lightAnimator;
|
||
LightBulbEmissionUpdate _lightBulbEmissionUpdate;
|
||
|
||
public List<FlickeringLightData> flickeringLightsData; // List of Lights and their maxIntensity
|
||
public List<FlickeringRendererData> flickeringRenderersData; // List of Renderers and their maxIntensity
|
||
|
||
public float minIntensity = 0f;
|
||
public float flickerSpeed = 500f; // Adjust this to control the overall speed of flickering
|
||
public float intensityVariation = 0.1f; // Adjust this to control the strength of the flickering effect
|
||
|
||
public int flickerSetCount = 25; // Number of flickers in a set before the pause
|
||
public float flickerSetPause = 1.5f; // Duration of the pause between flicker sets
|
||
|
||
private List<float> originalLightIntensities = new List<float>();
|
||
private List<float> originalRendererIntensities = new List<float>();
|
||
private List<Texture> originalEmissiveMaps = new List<Texture>();
|
||
private Dictionary<Renderer, List<Material>> emissiveMaterialsMap = new Dictionary<Renderer, List<Material>>(); // Store emissive materials for each Renderer
|
||
[HideInInspector] public bool isFlickering = false;
|
||
|
||
private SanityActivation[] sanity;
|
||
|
||
private void Start()
|
||
{
|
||
lightFlickerAudioSource = GetComponent<AudioSource>();
|
||
lightFlickerAudioSource.loop = true;
|
||
lightFlickerAudioSource.spatialBlend = 1f;
|
||
lightFlickerAudioSource.maxDistance = 10f;
|
||
//lightFlickerAudioClip = Resources.Load<AudioClip>("LightSounds/LightFlickerLoop");
|
||
|
||
if (flickeringLightsData == null || flickeringLightsData.Count == 0)
|
||
{
|
||
Debug.LogError("FlickeringLightsAndEmission script needs a list of lights data to flicker!");
|
||
return;
|
||
}
|
||
|
||
// Store the original intensities of all lights
|
||
foreach (FlickeringLightData data in flickeringLightsData)
|
||
{
|
||
originalLightIntensities.Add(data.light.intensity);
|
||
}
|
||
|
||
// Store the original emissive maps and intensities of all renderers with emissive materials
|
||
foreach (FlickeringRendererData data in flickeringRenderersData)
|
||
{
|
||
Renderer renderer = data.renderer;
|
||
List<Material> emissiveMaterials = new List<Material>();
|
||
|
||
// Filter out materials with emissive maps
|
||
foreach (Material material in renderer.materials)
|
||
{
|
||
if (material.GetTexture("_EmissiveColorMap"))
|
||
{
|
||
emissiveMaterials.Add(material);
|
||
// Store the original emissive exposure weights for each material
|
||
originalRendererIntensities.Add(material.GetFloat("_EmissiveExposureWeight"));
|
||
}
|
||
}
|
||
|
||
emissiveMaterialsMap.Add(renderer, emissiveMaterials);
|
||
|
||
// Store the original emissive maps for each material
|
||
foreach (Material emissiveMaterial in emissiveMaterials)
|
||
{
|
||
originalEmissiveMaps.Add(emissiveMaterial.GetTexture("_EmissiveColorMap"));
|
||
}
|
||
}
|
||
|
||
try
|
||
{
|
||
// Get all components in the children of the transform
|
||
sanity = GetComponentsInChildren<SanityActivation>();
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
// Handle exceptions here
|
||
Debug.LogError($"An error occurred: {e.Message}");
|
||
}
|
||
}
|
||
|
||
public void LightIsFlickering()
|
||
{
|
||
_lightAnimator.SetBool("IsFlickering", true);
|
||
if (!_lightAnimator.enabled) //If light animator is not enabled:
|
||
{
|
||
_lightAnimator.enabled = true; //Enable it.
|
||
}
|
||
if (!_lightBulbEmissionUpdate.UpdateEmission)
|
||
{
|
||
_lightBulbEmissionUpdate.UpdateEmission = true;
|
||
}
|
||
_lightBulbEmissionUpdate.IsFlickering = true;
|
||
}
|
||
|
||
public void LightIsNotFlickering()
|
||
{
|
||
_lightAnimator.SetBool("IsFlickering", false);
|
||
_lightBulbEmissionUpdate.ResetEmission();
|
||
if (!_lightAnimator.enabled) //If light animator is not enabled:
|
||
{
|
||
_lightAnimator.enabled = true; //Enable it.
|
||
}
|
||
_lightBulbEmissionUpdate.IsFlickering = false;
|
||
}
|
||
|
||
public void StartFlickering()
|
||
{
|
||
if (!isFlickering)
|
||
{
|
||
isFlickering = true;
|
||
//lightFlickerAudioSource.clip = lightFlickerAudioClip;
|
||
//lightFlickerAudioSource.Play();
|
||
RandomSoundsManager.GetInstance().PlayLightBussSound(lightFlickerAudioSource);
|
||
|
||
#region Sanity triggers
|
||
if (sanity.Length > 0)
|
||
{
|
||
foreach (var _sanity in sanity)
|
||
{
|
||
_sanity.DisableSanityTrigger();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
StartCoroutine(FlickerCoroutine());
|
||
}
|
||
}
|
||
|
||
public void StopFlickering()
|
||
{
|
||
if (isFlickering)
|
||
{
|
||
// Reset intensities of all lights to original values
|
||
for (int i = 0; i < flickeringLightsData.Count; i++)
|
||
{
|
||
if (flickeringLightsData[i] != null)
|
||
{
|
||
flickeringLightsData[i].light.intensity = originalLightIntensities[i];
|
||
}
|
||
}
|
||
|
||
// Reset intensities of all renderers to original values
|
||
for (int i = 0; i < flickeringRenderersData.Count; i++)
|
||
{
|
||
if (flickeringRenderersData[i] != null)
|
||
{
|
||
flickeringRenderersData[i].renderer.material.SetFloat("_EmissiveExposureWeight", originalRendererIntensities[i]);
|
||
}
|
||
}
|
||
|
||
// Reset emissive maps of all renderers to original values
|
||
for (int i = 0; i < flickeringRenderersData.Count; i++)
|
||
{
|
||
if (flickeringRenderersData[i] != null)
|
||
{
|
||
flickeringRenderersData[i].renderer.material.SetTexture("_EmissiveColorMap", originalEmissiveMaps[i]);
|
||
}
|
||
}
|
||
|
||
//Stop the flickering sound from all the lights
|
||
|
||
StopCoroutine(FlickerCoroutine());
|
||
StartCoroutine(StopAudioSourceAfterSeconds());
|
||
//lightFlickerAudioSource.clip = null;
|
||
//lightFlickerAudioSource.Stop();
|
||
#region Sanity triggers
|
||
if (sanity.Length > 0)
|
||
{
|
||
foreach (var _sanity in sanity)
|
||
{
|
||
_sanity.EnableSanityTrigger();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
isFlickering = false;
|
||
}
|
||
}
|
||
|
||
private IEnumerator FlickerCoroutine()
|
||
{
|
||
int flickerCount = 0;
|
||
|
||
while (isFlickering)
|
||
{
|
||
// 1. Υπολογίζουμε μία φορά το noise, κοινό για φως και emissive
|
||
float noise = Mathf.PerlinNoise(Time.time * flickerSpeed, 0f);
|
||
|
||
// 2. Υπολογισμός της νέας έντασης για τα φώτα
|
||
float flickerLightIntensity = Mathf.Lerp(minIntensity, flickeringLightsData[0].maxIntensity, noise * intensityVariation);
|
||
|
||
// 3. Εφαρμόζουμε την τιμή σε όλα τα φώτα
|
||
foreach (FlickeringLightData data in flickeringLightsData)
|
||
{
|
||
data.light.intensity = flickerLightIntensity;
|
||
}
|
||
|
||
// 4. Εφαρμόζουμε flicker στα emissive materials, με τον ίδιο ρυθμό (ίδιο noise)
|
||
foreach (FlickeringRendererData data in flickeringRenderersData)
|
||
{
|
||
Material[] materialsArray = data.renderer.materials;
|
||
|
||
foreach (var lightBulbRendMaterial in materialsArray)
|
||
{
|
||
int rendererIndex = flickeringRenderersData.IndexOf(data);
|
||
float originalEmissionIntensity = originalRendererIntensities[rendererIndex];
|
||
|
||
// Κρατάμε τον flicker παράγοντα πιο χαμηλό για να αποφεύγουμε υπερφωτισμούς
|
||
float flickerFactor = Mathf.Lerp(data.flickerFactorMin, data.flickerFactorMax, noise);
|
||
float flickerEmissionIntensity = originalEmissionIntensity * flickerFactor;
|
||
|
||
lightBulbRendMaterial.SetFloat("_EmissiveExposureWeight", flickerEmissionIntensity);
|
||
}
|
||
|
||
// Αν έχεις κάνει αλλαγές στα materials, ξαναπέρασέ τα
|
||
data.renderer.materials = materialsArray;
|
||
}
|
||
|
||
// 5. Διαχείριση flicker sets και παύσεων
|
||
flickerCount++;
|
||
if (flickerCount >= flickerSetCount)
|
||
{
|
||
flickerCount = 0; // reset
|
||
lightFlickerAudioSource.Stop();
|
||
yield return new WaitForSeconds(flickerSetPause);
|
||
float randomTime = Random.Range(0f, lightFlickerAudioSource.clip.length);
|
||
lightFlickerAudioSource.time = randomTime;
|
||
lightFlickerAudioSource.Play();
|
||
}
|
||
else
|
||
{
|
||
yield return new WaitForSeconds(0.1f); // μικρό delay ανά flicker
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private IEnumerator StopAudioSourceAfterSeconds()
|
||
{
|
||
yield return new WaitForSeconds(0.1f);
|
||
lightFlickerAudioSource.Stop();
|
||
print("Stop light flickering audio source");
|
||
}
|
||
private Texture2D CreateFlickerEmissiveMap(Texture originalEmissiveMap, float flickeringIntensity)
|
||
{
|
||
// Copy the original emissive map to a new RenderTexture
|
||
RenderTexture renderTexture = new RenderTexture(originalEmissiveMap.width, originalEmissiveMap.height, 0);
|
||
Graphics.Blit(originalEmissiveMap, renderTexture);
|
||
|
||
// Set the active RenderTexture for writing
|
||
RenderTexture.active = renderTexture;
|
||
|
||
// Create a new Texture2D to store the modified emissive map
|
||
Texture2D flickerEmissiveMap = new Texture2D(originalEmissiveMap.width, originalEmissiveMap.height);
|
||
flickerEmissiveMap.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
|
||
flickerEmissiveMap.Apply();
|
||
|
||
// Apply brightness modification to each pixel in the emissive map
|
||
Color[] pixels = flickerEmissiveMap.GetPixels();
|
||
for (int i = 0; i < pixels.Length; i++)
|
||
{
|
||
pixels[i] *= flickeringIntensity;
|
||
}
|
||
flickerEmissiveMap.SetPixels(pixels);
|
||
flickerEmissiveMap.Apply();
|
||
|
||
// Clean up RenderTexture
|
||
RenderTexture.active = null;
|
||
renderTexture.Release();
|
||
|
||
return flickerEmissiveMap;
|
||
}
|
||
}
|