Files
ShadingExercise/Assets/_Content/Scripts/RainExposure.cs
2026-09-08 09:38:09 +02:00

110 lines
2.8 KiB
C#

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);
}
}
}
}