294 lines
8.9 KiB
C#
294 lines
8.9 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
// Atrybut [InitializeOnLoad] musi byæ tutaj, nad deklaracj¹ klasy.
|
|
// Dziêki niemu statyczny konstruktor tej klasy zostanie wywo³any automatycznie przez edytor.
|
|
#if UNITY_EDITOR
|
|
[InitializeOnLoad]
|
|
#endif
|
|
[ExecuteAlways]
|
|
[RequireComponent(typeof(Collider))]
|
|
public class URPFogZone_Master : MonoBehaviour
|
|
{
|
|
#region Ustawienia Publiczne
|
|
[Header("Ustawienia Docelowe Mg³y")]
|
|
public bool targetFogEnabled = true;
|
|
public Color targetFogColor = new Color(0.5f, 0.5f, 0.5f);
|
|
public FogMode targetFogMode = FogMode.Exponential;
|
|
|
|
[Header("Ustawienia dla trybu Exponential / Exp2")]
|
|
[Range(0f, 1f)]
|
|
public float targetFogDensity = 0.02f;
|
|
|
|
[Header("Ustawienia dla trybu Linear")]
|
|
public float targetFogStartDistance = 0f;
|
|
public float targetFogEndDistance = 300f;
|
|
|
|
[Header("Ustawienia Przejœcia (tylko w trybie gry)")]
|
|
public float transitionDuration = 2.0f;
|
|
public string triggerTag = "MainCamera";
|
|
#endregion
|
|
|
|
#region Pola Prywatne i Statyczne
|
|
private static bool s_defaultsSaved = false;
|
|
private static bool s_defaultFogEnabled;
|
|
private static Color s_defaultFogColor;
|
|
private static FogMode s_defaultFogMode;
|
|
private static float s_defaultFogDensity;
|
|
private static float s_defaultFogStartDistance;
|
|
private static float s_defaultFogEndDistance;
|
|
|
|
private static URPFogZone_Master s_activeZone = null;
|
|
|
|
private Coroutine transitionCoroutine;
|
|
private Collider zoneCollider;
|
|
#endregion
|
|
|
|
#region Logika dla Edytora
|
|
#if UNITY_EDITOR
|
|
// Statyczny konstruktor. Wywo³ywany dziêki atrybutowi [InitializeOnLoad] nad klas¹.
|
|
static URPFogZone_Master()
|
|
{
|
|
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
|
}
|
|
|
|
private static void OnPlayModeStateChanged(PlayModeStateChange state)
|
|
{
|
|
if (state == PlayModeStateChange.ExitingPlayMode)
|
|
{
|
|
s_defaultsSaved = false;
|
|
s_activeZone = null;
|
|
}
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
if (Application.isPlaying) return;
|
|
if (s_activeZone == this)
|
|
{
|
|
ApplyTargetSettingsDirectly();
|
|
}
|
|
}
|
|
|
|
private void EditorUpdate()
|
|
{
|
|
if (Application.isPlaying) return;
|
|
|
|
var sceneView = SceneView.lastActiveSceneView;
|
|
if (sceneView == null || sceneView.camera == null) return;
|
|
|
|
if (zoneCollider == null) zoneCollider = GetComponent<Collider>();
|
|
if (zoneCollider == null) return;
|
|
|
|
bool isCurrentlyInside = zoneCollider.bounds.Contains(sceneView.camera.transform.position);
|
|
|
|
if (isCurrentlyInside && s_activeZone != this)
|
|
{
|
|
s_activeZone = this;
|
|
SaveDefaultFogSettings();
|
|
ApplyTargetSettingsDirectly();
|
|
}
|
|
else if (!isCurrentlyInside && s_activeZone == this)
|
|
{
|
|
s_activeZone = null;
|
|
RestoreDefaultSettings();
|
|
}
|
|
}
|
|
#endif
|
|
#endregion
|
|
|
|
#region Cykl ¯ycia Obiektu
|
|
private void OnEnable()
|
|
{
|
|
zoneCollider = GetComponent<Collider>();
|
|
zoneCollider.isTrigger = true;
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
EditorApplication.update += EditorUpdate;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (s_activeZone == this)
|
|
{
|
|
if (transitionCoroutine != null) StopCoroutine(transitionCoroutine);
|
|
RestoreDefaultSettings();
|
|
s_activeZone = null;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
EditorApplication.update -= EditorUpdate;
|
|
#endif
|
|
}
|
|
#endregion
|
|
|
|
#region Logika Trybu Gry
|
|
private void OnTriggerEnter(Collider other)
|
|
{
|
|
if (!Application.isPlaying || !other.CompareTag(triggerTag)) return;
|
|
|
|
SaveDefaultFogSettings();
|
|
s_activeZone = this;
|
|
StartTransition(true);
|
|
}
|
|
|
|
private void OnTriggerExit(Collider other)
|
|
{
|
|
if (!Application.isPlaying || !other.CompareTag(triggerTag)) return;
|
|
|
|
if (s_activeZone == this)
|
|
{
|
|
s_activeZone = null;
|
|
StartTransition(false);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
// =================================================================================
|
|
#region NOWOή: Publiczne Metody do sterowania przez Eventy (dla Cutscen)
|
|
|
|
/// <summary>
|
|
/// Aktywuje mg³ê z tej strefy. Podepnij tê funkcjê pod event na pocz¹tku cutsceny.
|
|
/// </summary>
|
|
public void ActivateZoneFog()
|
|
{
|
|
Debug.Log($"[FogZone] Rêczna aktywacja mg³y dla strefy: {gameObject.name}", this);
|
|
SaveDefaultFogSettings();
|
|
s_activeZone = this;
|
|
StartTransition(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Przywraca domyœlne ustawienia mg³y. Podepnij tê funkcjê pod event na koñcu cutsceny.
|
|
/// </summary>
|
|
public void RevertToDefaultFog()
|
|
{
|
|
// Sprawdzamy, czy TA strefa jest aktywna. To wa¿ne zabezpieczenie.
|
|
if (s_activeZone == this)
|
|
{
|
|
Debug.Log($"[FogZone] Rêczne przywracanie domyœlnej mg³y ze strefy: {gameObject.name}", this);
|
|
s_activeZone = null;
|
|
StartTransition(false);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
// =================================================================================
|
|
|
|
#region Metody G³ówne
|
|
private static void SaveDefaultFogSettings()
|
|
{
|
|
if (s_defaultsSaved) return;
|
|
|
|
s_defaultFogEnabled = RenderSettings.fog;
|
|
s_defaultFogColor = RenderSettings.fogColor;
|
|
s_defaultFogMode = RenderSettings.fogMode;
|
|
s_defaultFogDensity = RenderSettings.fogDensity;
|
|
s_defaultFogStartDistance = RenderSettings.fogStartDistance;
|
|
s_defaultFogEndDistance = RenderSettings.fogEndDistance;
|
|
s_defaultsSaved = true;
|
|
}
|
|
|
|
private static void RestoreDefaultSettings()
|
|
{
|
|
if (!s_defaultsSaved) return;
|
|
|
|
RenderSettings.fog = s_defaultFogEnabled;
|
|
RenderSettings.fogColor = s_defaultFogColor;
|
|
RenderSettings.fogMode = s_defaultFogMode;
|
|
RenderSettings.fogDensity = s_defaultFogDensity;
|
|
RenderSettings.fogStartDistance = s_defaultFogStartDistance;
|
|
RenderSettings.fogEndDistance = s_defaultFogEndDistance;
|
|
|
|
#if UNITY_EDITOR
|
|
SceneView.RepaintAll();
|
|
#endif
|
|
}
|
|
|
|
private void ApplyTargetSettingsDirectly()
|
|
{
|
|
RenderSettings.fog = targetFogEnabled;
|
|
RenderSettings.fogMode = targetFogMode;
|
|
RenderSettings.fogColor = targetFogColor;
|
|
RenderSettings.fogDensity = targetFogDensity;
|
|
RenderSettings.fogStartDistance = targetFogStartDistance;
|
|
RenderSettings.fogEndDistance = targetFogEndDistance;
|
|
|
|
#if UNITY_EDITOR
|
|
SceneView.RepaintAll();
|
|
#endif
|
|
}
|
|
|
|
private void StartTransition(bool toTarget)
|
|
{
|
|
if (transitionCoroutine != null)
|
|
{
|
|
StopCoroutine(transitionCoroutine);
|
|
}
|
|
transitionCoroutine = StartCoroutine(TransitionFogCoroutine(toTarget));
|
|
}
|
|
|
|
private IEnumerator TransitionFogCoroutine(bool toTarget)
|
|
{
|
|
float elapsed = 0f;
|
|
Color startColor = RenderSettings.fogColor;
|
|
float startDensity = RenderSettings.fogDensity;
|
|
float startStartDist = RenderSettings.fogStartDistance;
|
|
float startEndDist = RenderSettings.fogEndDistance;
|
|
|
|
Color finalColor = toTarget ? targetFogColor : s_defaultFogColor;
|
|
float finalDensity = toTarget ? targetFogDensity : s_defaultFogDensity;
|
|
float finalStartDist = toTarget ? targetFogStartDistance : s_defaultFogStartDistance;
|
|
float finalEndDist = toTarget ? targetFogEndDistance : s_defaultFogEndDistance;
|
|
|
|
if (toTarget)
|
|
{
|
|
RenderSettings.fog = targetFogEnabled;
|
|
RenderSettings.fogMode = targetFogMode;
|
|
}
|
|
else
|
|
{
|
|
RenderSettings.fogMode = s_defaultFogMode;
|
|
}
|
|
|
|
if (transitionDuration <= 0f)
|
|
{
|
|
RenderSettings.fogColor = finalColor;
|
|
RenderSettings.fogDensity = finalDensity;
|
|
RenderSettings.fogStartDistance = finalStartDist;
|
|
RenderSettings.fogEndDistance = finalEndDist;
|
|
if (!toTarget) RenderSettings.fog = s_defaultFogEnabled;
|
|
yield break;
|
|
}
|
|
|
|
while (elapsed < transitionDuration)
|
|
{
|
|
// U¿ywam unscaledDeltaTime, aby dzia³a³o poprawnie w cutscenach
|
|
elapsed += Time.unscaledDeltaTime;
|
|
float t = Mathf.Clamp01(elapsed / transitionDuration);
|
|
|
|
RenderSettings.fogColor = Color.Lerp(startColor, finalColor, t);
|
|
RenderSettings.fogDensity = Mathf.Lerp(startDensity, finalDensity, t);
|
|
RenderSettings.fogStartDistance = Mathf.Lerp(startStartDist, finalStartDist, t);
|
|
RenderSettings.fogEndDistance = Mathf.Lerp(startEndDist, finalEndDist, t);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
if (!toTarget)
|
|
{
|
|
RenderSettings.fog = s_defaultFogEnabled;
|
|
}
|
|
|
|
transitionCoroutine = null;
|
|
}
|
|
#endregion
|
|
} |