Files
Fishing2/Packages/com.waveharmonic.crest/Samples~/Waterfall/Scripts/Waterfall.cs
2026-01-31 00:32:49 +08:00

174 lines
4.4 KiB
C#

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest.Examples
{
[AddComponentMenu(Constants.k_MenuPrefixSample + "Waterfall (Sample)")]
[ExecuteAlways]
sealed class Waterfall : MonoBehaviour
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
public Transform _Crest;
public float _CrestRadius = 1f;
public Transform _Face;
public float _FaceAngle = 5f;
public Transform _Waves;
[Tooltip("The bottom of the waterfall. If unset, it will use sea level.")]
public Transform _PlungePool;
public Transform _Foam;
public float _FoamOffset;
public float _FoamPadding;
public Transform _Flow;
public float _FlowPadding = 10f;
float HeightFromPlungePool => transform.position.y - (_PlungePool != null
? _PlungePool.position.y
: WaterRenderer.Instance != null
? WaterRenderer.Instance.SeaLevel
: 0f);
void OnEnable()
{
Update();
}
void Update()
{
UpdateFace();
UpdateCrest();
UpdateWaves();
UpdateFoam();
UpdateFlow();
}
void UpdateCrest()
{
if (_Crest == null)
{
return;
}
var crest = _Crest;
var position = crest.localPosition;
position.y = -_CrestRadius;
crest.localPosition = position;
var scale = crest.localScale;
scale.x = _CrestRadius * 2f;
scale.z = _CrestRadius * 2f;
crest.localScale = scale;
}
void UpdateFace()
{
if (_Face == null)
{
return;
}
var face = _Face;
var angle = _FaceAngle * Mathf.Deg2Rad;
var ratio = 1f / Mathf.Cos(angle);
var height = HeightFromPlungePool - _CrestRadius;
var center = height * 0.5f;
var rotation = face.localRotation.eulerAngles;
rotation.x = 90f - _FaceAngle;
face.localRotation = Quaternion.Euler(rotation);
// Plane is 10m.
var scale = face.localScale;
scale.z = height * 0.1f * ratio;
face.localScale = scale;
var position = face.localPosition;
position.y = -center;
position.z = center * ratio * Mathf.Sin(angle);
position.y += -_CrestRadius;
position.z += _CrestRadius;
face.localPosition = position;
}
void UpdateWaves()
{
if (_Waves == null)
{
return;
}
var waves = _Waves;
var feather = 0f;
if (_Waves.TryGetComponent<Renderer>(out var renderer) && renderer.sharedMaterial != null && renderer.sharedMaterial.IsKeywordEnabled("d_Feather"))
{
feather = renderer.sharedMaterial.GetFloat(Shader.PropertyToID("_Crest_FeatherWidth"));
}
var position = waves.localPosition;
var scale = waves.localScale.x;
position.z = scale * 0.5f + (_Face.localPosition.z * 2f - _CrestRadius) - feather * scale;
position.y = -HeightFromPlungePool;
waves.localPosition = position;
}
void UpdateFoam()
{
if (_Foam == null)
{
return;
}
var foam = _Foam;
var size = _Face.localPosition.z * 2f - _CrestRadius;
var scale = foam.localScale;
scale.y = size + _FoamPadding;
foam.localScale = scale;
var position = _Foam.localPosition;
position.z = size * 0.5f + _FoamOffset;
_Foam.localPosition = position;
}
void UpdateFlow()
{
if (_Flow == null)
{
return;
}
var flow = _Flow;
var size = _Face.localPosition.z * 2f - _CrestRadius;
var scale = flow.localScale;
scale.y = size + _FlowPadding;
flow.localScale = scale;
var position = _Flow.localPosition;
position.z = size * 0.5f;
_Flow.localPosition = position;
}
}
}