using System.Collections; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif [ExecuteAlways] [RequireComponent(typeof(Collider))] public class URPFogZone_Master : MonoBehaviour { // --- Publiczne pola --- [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"; // --- Prywatne i statyczne pola --- 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; // NOWOŚĆ: Śledzi, która strefa jest obecnie aktywna. private static URPFogZone_Master s_activeZone = null; private Coroutine transitionCoroutine; private Collider zoneCollider; #if UNITY_EDITOR private bool isEditorCameraInZone = false; #endif // --- Cykl życia --- private void OnEnable() { zoneCollider = GetComponent(); SaveDefaultFogSettings(); #if UNITY_EDITOR EditorApplication.update += EditorUpdate; #endif } private void OnDisable() { // Jeśli ten obiekt był ostatnią aktywną strefą, przywróć domyślne ustawienia. if (s_activeZone == this) { if (transitionCoroutine != null) StopCoroutine(transitionCoroutine); RestoreDefaultSettings(); s_activeZone = null; } #if UNITY_EDITOR EditorApplication.update -= EditorUpdate; #endif } // --- Logika dla trybu edycji --- #if UNITY_EDITOR private void OnValidate() { if (Application.isPlaying) return; // Zastosuj zmiany tylko jeśli ta strefa jest aktywna if (s_activeZone == this) { ApplyTargetSettingsDirectly(); } } private void EditorUpdate() { if (Application.isPlaying) return; var sceneView = SceneView.lastActiveSceneView; if (sceneView == null || sceneView.camera == null) return; bool isCurrentlyInside = zoneCollider.bounds.Contains(sceneView.camera.transform.position); // WEJŚCIE do strefy if (isCurrentlyInside && s_activeZone != this) { s_activeZone = this; isEditorCameraInZone = true; ApplyTargetSettingsDirectly(); } // WYJŚCIE ze strefy else if (!isCurrentlyInside && s_activeZone == this) { s_activeZone = null; isEditorCameraInZone = false; RestoreDefaultSettings(); } } #endif // --- Logika dla trybu gry --- private void OnTriggerEnter(Collider other) { if (!Application.isPlaying || !other.CompareTag(triggerTag)) return; s_activeZone = this; StartTransition(true); } private void OnTriggerExit(Collider other) { if (!Application.isPlaying || !other.CompareTag(triggerTag)) return; // Przywróć domyślne tylko jeśli opuszczamy TĘ aktywną strefę. if (s_activeZone == this) { s_activeZone = null; StartTransition(false); } } // --- Wspólne metody --- 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 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 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 StartTransition(bool toTarget) { if (transitionCoroutine != null) StopCoroutine(transitionCoroutine); transitionCoroutine = StartCoroutine(TransitionFogCoroutine(toTarget)); } 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; RenderSettings.fog = toTarget ? targetFogEnabled : s_defaultFogEnabled; RenderSettings.fogMode = toTarget ? targetFogMode : s_defaultFogMode; while (elapsed < transitionDuration) { elapsed += Time.deltaTime; float t = (transitionDuration > 0) ? Mathf.Clamp01(elapsed / transitionDuration) : 1f; 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; } transitionCoroutine = null; } }