using System; using UnityEngine; public class RainExposure : MonoBehaviour { [Serializable] public class Settings { public float RipplesSpeed = 2f; public float WetSpeed = .5f; public float RaycastDistance = 50f; } [Serializable] public class References { public Shader Shader; public Renderer[] Renderers; } [Serializable] public class State { [Range(0f, 1f)] public float Ripples; [Range(0f, 1f)] public float Wet; } [SerializeField] private Settings _settings; [SerializeField] private References _references; [SerializeField] private State _state; private bool covered; private float coverDistance; private static readonly int RipplesId = Shader.PropertyToID("_Ripples"); private static readonly int WetId = Shader.PropertyToID("_Wet"); private readonly RaycastHit[] _hits = new RaycastHit[32]; void OnDrawGizmosSelected() { Color col = Color.white; if (Application.isPlaying) col = covered ? Color.green : Color.red; Gizmos.color = col; Gizmos.DrawLine(transform.position, transform.position + Vector3.up * (covered ? coverDistance : _settings.RaycastDistance)); } void Update() { float t = Time.deltaTime; covered = IsCovered(); float target = covered ? 0f : 1f; _state.Ripples = Mathf.MoveTowards(_state.Ripples, target, _settings.RipplesSpeed * t); _state.Wet = Mathf.MoveTowards(_state.Wet, target, _settings.WetSpeed * t); SetMaterials(); } private bool IsCovered() { int hitCount = Physics.RaycastNonAlloc(transform.position, Vector3.up, _hits, _settings.RaycastDistance); for (int i = 0; i < hitCount; i++) { Collider col = _hits[i].collider; if (!col) continue; if (col.transform == transform || col.transform.IsChildOf(transform)) continue; coverDistance = _hits[i].distance; return true; } return false; } private void SetMaterials() { if (!_references.Shader || _references.Renderers == null) return; for (int i = 0; i < _references.Renderers.Length; i++) { Renderer rend = _references.Renderers[i]; if (rend == null) continue; Material[] mats = rend.materials; for (int j = 0; j < mats.Length; j++) { Material mat = mats[j]; if (mat == null || mat.shader != _references.Shader) continue; mat.SetFloat(RipplesId, _state.Ripples); mat.SetFloat(WetId, _state.Wet); } } } }