Files
2026-02-21 16:45:37 +08:00

218 lines
7.0 KiB
C#

using UnityEngine;
using UnityEngine.Serialization;
namespace UltimateWater
{
public class ShipBowWavesEmitter : MonoBehaviour
{
[FormerlySerializedAs("gpuParticleSystem")]
[SerializeField]
private WaveParticlesSystemGPU _GPUParticleSystem;
[FormerlySerializedAs("unityParticleSystem")]
[SerializeField]
private ParticleSystem _UnityParticleSystem;
[FormerlySerializedAs("waveSpeed")]
[SerializeField]
[Range(0.02f, 0.98f)]
private float _WaveSpeed = 0.5f;
[FormerlySerializedAs("amplitude")]
[SerializeField]
private float _Amplitude = 0.5f;
[FormerlySerializedAs("wavelength")]
[SerializeField]
private float _Wavelength = 6f;
[FormerlySerializedAs("lifetime")]
[SerializeField]
private float _Lifetime = 50f;
[FormerlySerializedAs("foam")]
[SerializeField]
private float _Foam = 1f;
[FormerlySerializedAs("maxShipSpeed")]
[SerializeField]
private float _MaxShipSpeed = 16.5f;
[FormerlySerializedAs("leftRightSpace")]
[SerializeField]
private float _LeftRightSpace = 1f;
[FormerlySerializedAs("trailCalming")]
[SerializeField]
[Range(0f, 1f)]
private float _TrailCalming = 1f;
[FormerlySerializedAs("trailFoam")]
[SerializeField]
[Range(0f, 8f)]
private float _TrailFoam = 1f;
[SerializeField]
[FormerlySerializedAs("advancedEmissionPositioning")]
[Header("Advanced")]
[Tooltip("Use for submarines. Allows emission to be moved to exposed ship parts during submerge process and completely disabled after complete submarge.")]
private bool _AdvancedEmissionPositioning;
[FormerlySerializedAs("shipCollider")]
[SerializeField]
[Tooltip("Required if 'advancedEmissionPositioning' is enabled. Allows emitter to determine an emission point on that collider.")]
private Collider _ShipCollider;
[FormerlySerializedAs("advancedEmissionOffset")]
[SerializeField]
private float _AdvancedEmissionOffset = 2f;
[FormerlySerializedAs("minTextureIndex")]
[SerializeField]
private int _MinTextureIndex;
[FormerlySerializedAs("maxTextureIndex")]
[SerializeField]
private int _MaxTextureIndex = 4;
[FormerlySerializedAs("emissionSpacing")]
[SerializeField]
[Range(0.1f, 1f)]
private float _EmissionSpacing = 0.45f;
private Vector2 _PreviousFrameBowPosition;
private float _TotalBowDeltaMagnitude;
private float _LastBowEmitTime;
private float _AngleSin;
private float _AngleCos;
private float _Space;
private bool _UseBuiltinParticleSystem;
private Water _WaterComponent;
private void Start()
{
if (_GPUParticleSystem == null)
{
_GPUParticleSystem = Object.FindObjectOfType<WaveParticlesSystemGPU>();
}
_UseBuiltinParticleSystem = _UnityParticleSystem == null;
_WaterComponent = _GPUParticleSystem.GetComponent<Water>();
OnValidate();
Vector2 vector = GetVector2(base.transform.position);
Vector2 previousFrameBowPosition = vector + _WaterComponent.SurfaceOffset;
_PreviousFrameBowPosition = previousFrameBowPosition;
}
private void OnValidate()
{
_Space = _Wavelength * _EmissionSpacing;
float f = Mathf.Acos(_WaveSpeed);
_AngleSin = Mathf.Sin(f);
_AngleCos = Mathf.Cos(f);
}
private void LateUpdate()
{
Vector2 vector = GetVector2(base.transform.position);
Vector2 vector2 = vector + _WaterComponent.SurfaceOffset;
Vector2 vector3 = vector2 - _PreviousFrameBowPosition;
Vector2 normalized = GetVector2(base.transform.forward).normalized;
_PreviousFrameBowPosition = vector2;
float num = vector3.x * normalized.x + vector3.y * normalized.y;
if (num < 0f)
{
return;
}
float num2 = num;
_TotalBowDeltaMagnitude += num2;
if (!(_TotalBowDeltaMagnitude >= _Space))
{
return;
}
float time = Time.time;
float num3 = time - _LastBowEmitTime;
_LastBowEmitTime = time;
float num4 = _TotalBowDeltaMagnitude / num3;
if (num4 >= _MaxShipSpeed)
{
num4 = _MaxShipSpeed;
}
float num5 = _WaveSpeed * num4;
Vector2 vector4 = new Vector2(normalized.x * _AngleCos - normalized.y * _AngleSin, normalized.x * _AngleSin + normalized.y * _AngleCos);
Vector2 vector5 = new Vector2(normalized.x * _AngleCos + normalized.y * _AngleSin, normalized.y * _AngleCos - normalized.x * _AngleSin);
Vector2 normalized2 = GetVector2(base.transform.right).normalized;
do
{
_TotalBowDeltaMagnitude -= _Space;
if (_AdvancedEmissionPositioning)
{
float y = _WaterComponent.transform.position.y + _WaterComponent.GetHeightAt(vector.x, vector.y, time);
RaycastHit hitInfo;
if (!_ShipCollider.Raycast(new Ray(new Vector3(vector.x, y, vector.y), new Vector3(0f - normalized.x, 0f, 0f - normalized.y)), out hitInfo, 100f))
{
break;
}
vector = GetVector2(hitInfo.point) + normalized * _AdvancedEmissionOffset;
}
Vector2 horizontalDisplacementAt = _WaterComponent.GetHorizontalDisplacementAt(vector.x, vector.y, time);
vector.x -= horizontalDisplacementAt.x;
vector.y -= horizontalDisplacementAt.y;
if (_UseBuiltinParticleSystem)
{
_GPUParticleSystem.EmitParticle(new WaveParticlesSystemGPU.ParticleData
{
Position = vector + normalized2 * _LeftRightSpace,
Direction = vector5 * num5,
Amplitude = _Amplitude,
Wavelength = _Wavelength,
InitialLifetime = _Lifetime,
Lifetime = _Lifetime,
Foam = _Foam,
UvOffsetPack = (float)Random.Range(0, _GPUParticleSystem.FoamAtlasHeight) / (float)_GPUParticleSystem.FoamAtlasHeight * 16f + (float)Random.Range(_MinTextureIndex, _MaxTextureIndex) / (float)_GPUParticleSystem.FoamAtlasWidth,
TrailCalming = _TrailCalming,
TrailFoam = _TrailFoam
});
_GPUParticleSystem.EmitParticle(new WaveParticlesSystemGPU.ParticleData
{
Position = vector + normalized2 * (0f - _LeftRightSpace),
Direction = vector4 * num5,
Amplitude = _Amplitude,
Wavelength = _Wavelength,
InitialLifetime = _Lifetime,
Lifetime = _Lifetime,
Foam = _Foam,
UvOffsetPack = (float)Random.Range(0, _GPUParticleSystem.FoamAtlasHeight) / (float)_GPUParticleSystem.FoamAtlasHeight * 16f + (float)Random.Range(_MinTextureIndex, _MaxTextureIndex) / (float)_GPUParticleSystem.FoamAtlasWidth,
TrailCalming = _TrailCalming,
TrailFoam = _TrailFoam
});
}
else
{
ParticleSystem.EmitParams emitParams = new ParticleSystem.EmitParams
{
position = new Vector3(vector.x + normalized2.x * _LeftRightSpace, _WaterComponent.transform.position.y, vector.y + normalized2.y * _LeftRightSpace),
velocity = new Vector3(vector5.x, 0f, vector5.y) * num5
};
_UnityParticleSystem.Emit(emitParams, 1);
emitParams.position = new Vector3(vector.x + normalized2.x * (0f - _LeftRightSpace), emitParams.position.y, vector.y + normalized2.y * (0f - _LeftRightSpace));
emitParams.velocity = new Vector3(vector4.x, 0f, vector4.y) * num5;
_UnityParticleSystem.Emit(emitParams, 1);
}
}
while (_TotalBowDeltaMagnitude >= _Space);
}
private static Vector2 GetVector2(Vector3 vector3)
{
return new Vector2(vector3.x, vector3.z);
}
}
}