using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering.HighDefinition; using UnityEngine.VFX; using UnityWaterTools; public class FishingLineFX : WaterFXInstance, IBatchUpdate { private struct DecalInstanceData { public WaterDecal Decal; public float StartTime; public float StartAmplitude; } [Header("References")] [SerializeField] private PlayerFishingGearController _gearController; [SerializeField] private WaterDecal _decalPrefab; [SerializeField] private VisualEffect _splashPrefab; private FishingSetController _fishingSetController; private WaterFloater _waterFloater; private Transform _rodEnd; private Transform _lineEnd; private LayerMask _layerMask; private Vector3 _intersectionPoint; private Vector3 _rayDirection; private const float INTERVAL = 0.05f; private float _time; private List _activeDecals; [Header("Debug")] [SerializeField] private bool _drawIntersectionPoint; [SerializeField] [Range(0.01f, 1f)] private float _intersectionPointSize = 0.1f; [SerializeField] private Color _intersectionPointColor = Color.purple; [SerializeField] private bool _drawLine; [SerializeField] private Color _lineColor = Color.red; [SerializeField] private bool _drawHalfLine; [SerializeField] private Color _halfLineColor = Color.blue; private void Start() { if (_gearController != null) { _gearController.OnFishingSetEquiped += Activate; _gearController.OnFishingSetUnequip += Deactivate; } _layerMask = LayerMask.GetMask("Water"); _activeDecals = new List(); } public void Activate(FishingSetController fishingSetController) { Init(); _pool = _manager.GetPool(_decalPrefab); _fishingSetController = fishingSetController; _waterFloater = _fishingSetController.AttachedLure.GetComponent(); if (_waterFloater != null) { _waterFloater.OnWaterEnter += ActivateSplash; } _rodEnd = _fishingSetController.AttachedRod.RodTipBone.transform; _lineEnd = _fishingSetController.AttachedLure.transform; _fishingSetController.OnGearDestroyed += Deactivate; } protected override void Deactivate() { base.Deactivate(); if (_waterFloater != null) { _waterFloater.OnWaterEnter -= ActivateSplash; } _waterFloater = null; _fishingSetController.OnGearDestroyed -= Deactivate; _rodEnd = null; _lineEnd = null; } protected override void OnDestroy() { Deactivate(); base.OnDestroy(); } public void ActivateSplash(bool inWater) { if (inWater) { _manager.CreateSplash(_waterFloater.transform.position, 1f); } } public override void BatchUpdate() { CalculateLineWaterIntersection(); base.transform.position = _intersectionPoint; UpdateFX(); } private void CalculateLineWaterIntersection() { if (!(_lineEnd == null) && !(_rodEnd == null)) { _rayDirection = (_lineEnd.position - _rodEnd.position).normalized; if (Physics.Raycast(_rodEnd.position, _rayDirection, out var hitInfo, _manager.MaxSpawnDistanceFromCamera, _layerMask)) { Debug.DrawRay(_rodEnd.position, _rayDirection); _intersectionPoint = hitInfo.point; } } } public override void UpdateFX() { if (_activeDecals != null && _activeDecals.Count > 0) { float num = 0f; for (int num2 = _activeDecals.Count - 1; num2 >= 0; num2--) { num = Mathf.Clamp01((Time.realtimeSinceStartup - _activeDecals[num2].StartTime) * _decalDecaySpeed); if (num >= 1f) { _pool.Reclaim(_activeDecals[num2].Decal); _activeDecals.RemoveAt(num2); } else { _activeDecals[num2].Decal.amplitude = (1f - num) * _activeDecals[num2].StartAmplitude; _activeDecals[num2].Decal.transform.localScale = new Vector3(0.5f * num, 1f, 0.5f * num); } } } _time += Time.deltaTime; if (!(_gearController == null) && !(_waterFloater == null) && !(_time < 0.05f) && IsVisible && _waterFloater.InWater && !((float)_gearController.LineTension < 0.1f)) { _time = 0f; WaterDecal instance = _pool.GetInstance(); instance.amplitude = _decalAmplitude; instance.transform.position = base.transform.position; instance.transform.rotation = Quaternion.identity; instance.transform.localScale = Vector3.zero; instance.gameObject.SetActive(value: true); _activeDecals.Add(new DecalInstanceData { Decal = instance, StartTime = Time.realtimeSinceStartup, StartAmplitude = _decalAmplitude }); } } }