using System.Collections; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif /// /// Zarządza lokalną strefą mgły URP. Zmienia globalne ustawienia RenderSettings /// z płynnym przejściem. Działa w trybie gry (triggery, eventy) oraz w edytorze (podgląd). /// [ExecuteAlways] [RequireComponent(typeof(Collider))] public class FogZone : MonoBehaviour { [Header("Ustawienia Docelowe Mgły (Wewnątrz Strefy)")] public Color targetFogColor = new Color(0.5f, 0.5f, 0.5f); public FogMode targetFogMode = FogMode.Exponential; [Range(0f, 1f)] public float targetFogDensity = 0.02f; public float targetFogStartDistance = 0f; public float targetFogEndDistance = 300f; [Header("Ustawienia Zachowania")] [Tooltip("Czas w sekundach, w jakim mgła będzie płynnie przechodzić do nowych ustawień.")] public float transitionDuration = 2.0f; [Tooltip("Tag obiektu (zazwyczaj gracza), który ma aktywować strefę.")] public string playerTag = "Player"; [Header("Ustawienia Edytora")] [Tooltip("Włącza podgląd mgły w edytorze, gdy kamera Scene View wejdzie do strefy.")] public bool enableEditorPreview = true; // Statyczne, by zapewnić, że tylko jedna zmiana mgły dzieje się naraz w całej grze private static Coroutine s_transitionCoroutine; private static MonoBehaviour s_coroutineRunner; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void InitializeOnLoad() { s_transitionCoroutine = null; s_coroutineRunner = null; } // --- LOGIKA TRYBU GRY --- private void OnTriggerEnter(Collider other) { if (Application.isPlaying && other.CompareTag(playerTag)) { StartTransition(true); } } private void OnTriggerExit(Collider other) { if (Application.isPlaying && other.CompareTag(playerTag)) { StartTransition(false); } } // --- PUBLICZNE METODY DLA EVENTÓW (CUTSCENY) --- public void ActivateZoneFogFromEvent() { if (!Application.isPlaying) return; StartTransition(true); } public void RevertToDefaultFogFromEvent() { if (!Application.isPlaying) return; StartTransition(false); } // --- GŁÓWNA LOGIKA PRZEJŚCIA --- private void StartTransition(bool toZoneSettings) { if (s_transitionCoroutine != null && s_coroutineRunner != null) { s_coroutineRunner.StopCoroutine(s_transitionCoroutine); } s_coroutineRunner = this; s_transitionCoroutine = StartCoroutine(TransitionFog(toZoneSettings)); } private IEnumerator TransitionFog(bool toZoneSettings) { Color startColor = RenderSettings.fogColor; float startDensity = RenderSettings.fogDensity; float startLinearStart = RenderSettings.fogStartDistance; float startLinearEnd = RenderSettings.fogEndDistance; Color endColor; FogMode endMode; float endDensity; float endLinearStart; float endLinearEnd; if (toZoneSettings) { endColor = targetFogColor; endMode = targetFogMode; endDensity = targetFogDensity; endLinearStart = targetFogStartDistance; endLinearEnd = targetFogEndDistance; RenderSettings.fogMode = endMode; } else { var defaults = FogDefaultSettings.Instance; if (defaults == null) { Debug.LogError("Nie znaleziono FogDefaultSettings w scenie!", this); yield break; } endColor = defaults.fogColor; endMode = defaults.fogMode; endDensity = defaults.fogDensity; endLinearStart = defaults.fogStartDistance; endLinearEnd = defaults.fogEndDistance; } RenderSettings.fog = true; float elapsed = 0f; while (elapsed < transitionDuration) { float t = (transitionDuration > 0) ? Mathf.Clamp01(elapsed / transitionDuration) : 1f; RenderSettings.fogColor = Color.Lerp(startColor, endColor, t); RenderSettings.fogDensity = Mathf.Lerp(startDensity, endDensity, t); RenderSettings.fogStartDistance = Mathf.Lerp(startLinearStart, endLinearStart, t); RenderSettings.fogEndDistance = Mathf.Lerp(startLinearEnd, endLinearEnd, t); elapsed += Time.deltaTime; yield return null; } RenderSettings.fogColor = endColor; RenderSettings.fogDensity = endDensity; RenderSettings.fogStartDistance = endLinearStart; RenderSettings.fogEndDistance = endLinearEnd; if (!toZoneSettings && FogDefaultSettings.Instance != null) { RenderSettings.fogMode = FogDefaultSettings.Instance.fogMode; RenderSettings.fog = FogDefaultSettings.Instance.fogEnabled; } s_transitionCoroutine = null; s_coroutineRunner = null; } // --- LOGIKA TYLKO DLA EDYTORA UNITY --- #if UNITY_EDITOR private static bool s_editorSettingsSaved = false; private static FogZone s_editorActiveZone = null; private static bool s_prevFogEnabled; private static Color s_prevFogColor; private static FogMode s_prevFogMode; private static float s_prevFogDensity; private static float s_prevFogStartDist; private static float s_prevFogEndDist; private void OnEnable() { var col = GetComponent(); if (col != null) col.isTrigger = true; if (!Application.isPlaying) { EditorApplication.update += EditorUpdate; } } private void OnDisable() { if (!Application.isPlaying) { EditorApplication.update -= EditorUpdate; if (s_editorActiveZone == this) { RestoreEditorSettings(); s_editorActiveZone = null; } } } private void EditorUpdate() { if (Application.isPlaying) return; // *** POPRAWKA JEST TUTAJ *** // Jeśli podgląd jest wyłączony, ale ta strefa jest wciąż aktywna, przywróć ustawienia if (!enableEditorPreview) { if (s_editorActiveZone == this) { RestoreEditorSettings(); s_editorActiveZone = null; } return; // Zakończ działanie metody, jeśli podgląd jest wyłączony } var sceneView = SceneView.lastActiveSceneView; if (sceneView == null || sceneView.camera == null) return; var zoneCollider = GetComponent(); if (zoneCollider == null) return; bool isCameraInside = zoneCollider.bounds.Contains(sceneView.camera.transform.position); if (isCameraInside) { if (s_editorActiveZone != this) { if (s_editorActiveZone == null) { SaveEditorSettings(); } s_editorActiveZone = this; ApplyZoneSettingsDirectly(); } } else { if (s_editorActiveZone == this) { RestoreEditorSettings(); s_editorActiveZone = null; } } } private void OnValidate() { if (!Application.isPlaying && s_editorActiveZone == this) { ApplyZoneSettingsDirectly(); } } private static void SaveEditorSettings() { if (s_editorSettingsSaved) return; s_prevFogEnabled = RenderSettings.fog; s_prevFogColor = RenderSettings.fogColor; s_prevFogMode = RenderSettings.fogMode; s_prevFogDensity = RenderSettings.fogDensity; s_prevFogStartDist = RenderSettings.fogStartDistance; s_prevFogEndDist = RenderSettings.fogEndDistance; s_editorSettingsSaved = true; } private void ApplyZoneSettingsDirectly() { RenderSettings.fog = true; RenderSettings.fogMode = targetFogMode; RenderSettings.fogColor = targetFogColor; RenderSettings.fogDensity = targetFogDensity; RenderSettings.fogStartDistance = targetFogStartDistance; RenderSettings.fogEndDistance = targetFogEndDistance; SceneView.RepaintAll(); } private static void RestoreEditorSettings() { if (!s_editorSettingsSaved) return; RenderSettings.fog = s_prevFogEnabled; RenderSettings.fogColor = s_prevFogColor; RenderSettings.fogMode = s_prevFogMode; RenderSettings.fogDensity = s_prevFogDensity; RenderSettings.fogStartDistance = s_prevFogStartDist; RenderSettings.fogEndDistance = s_prevFogEndDist; s_editorSettingsSaved = false; SceneView.RepaintAll(); } #endif }