Files
beyond/Assets/Scripts/URPFogZone.cs
2025-07-18 16:44:42 +02:00

331 lines
10 KiB
C#

// --- PE£NY I POPRAWIONY SKRYPT FOGZONE.CS ---
using System.Collections;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// 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).
/// </summary>
[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;
}
// --- NOWA LOGIKA - SPRAWDZENIE NA STARCIE GRY ---
/// <summary>
/// Sprawdza na starcie gry, czy gracz ju¿ znajduje siê w strefie.
/// Jeœli tak, aktywuje mg³ê natychmiast.
/// </summary>
private void Start()
{
// Upewniamy siê, ¿e ten kod dzia³a tylko w trybie gry, a nie w edytorze
if (!Application.isPlaying)
{
return;
}
// ZnajdŸ obiekt gracza na scenie za pomoc¹ tagu
GameObject playerObject = GameObject.FindWithTag(playerTag);
if (playerObject == null)
{
// Jeœli nie ma gracza na scenie (lub ma z³y tag), nic nie robimy
return;
}
// Pobierz collider tej strefy mg³y
Collider zoneCollider = GetComponent<Collider>();
// SprawdŸ, czy pozycja gracza znajduje siê wewn¹trz granic collidera tej strefy
if (zoneCollider.bounds.Contains(playerObject.transform.position))
{
Debug.Log($"Gracz '{playerObject.name}' rozpocz¹³ grê wewn¹trz strefy '{this.name}'. Ustawiam mg³ê natychmiast.", this);
// U¿ywamy ma³ej sztuczki: tymczasowo ustawiamy czas przejœcia na 0,
// aby mg³a pojawi³a siê od razu, a nie p³ynnie.
float originalDuration = transitionDuration;
transitionDuration = 0f;
// Uruchom logikê wejœcia do strefy
StartTransition(true);
// Przywróæ oryginalny czas przejœcia, aby póŸniejsze wejœcia/wyjœcia
// dzia³a³y z normaln¹, p³ynn¹ animacj¹.
transitionDuration = originalDuration;
}
}
// --- LOGIKA TRYBU GRY (BEZ ZMIAN) ---
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 (BEZ ZMIAN) ---
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)
{
// Jeœli czas przejœcia jest 0 (jak w naszym przypadku na starcie), 't' od razu bêdzie 1
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;
}
// Upewniamy siê, ¿e na koñcu s¹ dok³adnie docelowe wartoœci
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 (BEZ ZMIAN) ---
#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<Collider>();
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;
if (!enableEditorPreview)
{
if (s_editorActiveZone == this)
{
RestoreEditorSettings();
s_editorActiveZone = null;
}
return;
}
var sceneView = SceneView.lastActiveSceneView;
if (sceneView == null || sceneView.camera == null) return;
var zoneCollider = GetComponent<Collider>();
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
}