using System; using BrewMonster.Scripts; using UnityEngine; namespace BrewMonster.PerfectWorld.Scripts.Vfx { public enum GFX_STATE { ST_STOP = 0, ST_PLAY = 1, ST_PAUSE = 2, ST_EDITMODE = 3 } public class BaseVfxObject : MonoBehaviour { [SerializeField] private ParticleSystem _vfx; [SerializeField] private float _lifeTime =-1; [SerializeField] private bool _isLoopVfx; private string _vfxPath; private Vector3 _originalScale = Vector3.one; private Vector3 _offset = Vector3.zero; [SerializeField]private GFX_STATE m_iState; private float _elapsedTime = 0f; private bool _lifetimeCompleted = false; /// /// 生命周期完成事件 / Event triggered when lifetime is completed /// public event Action OnLifetimeCompleted; private void Awake() { if (_vfx == null) { _vfx = GetComponent(); } if (_vfx != null) { _originalScale = _vfx.transform.localScale; } } private void OnDestroy() { if(!string.IsNullOrEmpty(_vfxPath)) { AddressableManager.Instance.UnloadAsset(_vfxPath); } } private void Update() { if(_isLoopVfx) return; if (_lifeTime > 0 && m_iState == GFX_STATE.ST_PLAY && !_lifetimeCompleted) { _elapsedTime += Time.deltaTime; if (_elapsedTime >= _lifeTime) { _lifetimeCompleted = true; Stop(); OnLifetimeCompleted?.Invoke(); } } } public void Init(string vfxPath) { _vfxPath = vfxPath; } #region EC public GFX_STATE GetState() { return m_iState; } #endregion /// /// Set VFX scale /// public void SetScale(float scale) { SetScale(new Vector3(scale, scale, scale)); } /// /// Set VFX scale with vector /// public void SetScale(Vector3 scale) { if (_vfx != null) { _vfx.transform.localScale = Vector3.Scale(_originalScale, scale); // 调整粒子大小 / Adjust particle size var main = _vfx.main; main.startSizeMultiplier *= scale.magnitude / Mathf.Sqrt(3); } } /// /// Set VFX offset /// public void SetOffset(Vector3 offset) { _offset = offset; if (_vfx != null) { _vfx.transform.localPosition = offset; } } /// /// Set VFX world position /// public void SetPosition(Vector3 position) { if (_vfx != null) { _vfx.transform.position = position; } } /// /// Set VFX rotation /// public void SetRotation(Quaternion rotation) { if (_vfx != null) { _vfx.transform.rotation = rotation; } } /// /// Set VFX rotation with euler angles /// public void SetRotation(Vector3 eulerAngles) { SetRotation(Quaternion.Euler(eulerAngles)); } /// /// Set VFX color /// public void SetColor(Color color) { if (_vfx != null) { var main = _vfx.main; main.startColor = color; } } /// /// Set VFX duration /// public void SetDuration(float duration) { if (_vfx != null) { var main = _vfx.main; main.duration = duration; } } /// /// Set VFX playback speed /// public void SetSpeed(float speed) { if (_vfx != null) { var main = _vfx.main; main.simulationSpeed = speed; } } /// /// Play VFX /// public void Play() { Stop(); if (_vfx != null) { m_iState = GFX_STATE.ST_PLAY; gameObject.SetActive(true); _vfx.Play(); // 重置生命周期计时器 / Reset lifetime timer _elapsedTime = 0f; _lifetimeCompleted = false; } } /// /// Stop VFX /// public void Stop(bool resetParent = false) { if (_vfx != null) { m_iState = GFX_STATE.ST_STOP; _vfx.Stop(); gameObject.SetActive(false); if(resetParent) gameObject.transform.parent = null; } } /// /// Pause VFX /// public void Pause() { if (_vfx != null) { m_iState = GFX_STATE.ST_PAUSE; _vfx.Pause(); } } /// /// Clear all VFX particles /// public void Clear() { if (_vfx != null) { _vfx.Clear(); } } /// /// 重新开始播放 / Restart VFX /// public void Restart() { if (_vfx != null) { _vfx.Stop(); _vfx.Clear(); _vfx.Play(); // 重置生命周期计时器 / Reset lifetime timer m_iState = GFX_STATE.ST_PLAY; _elapsedTime = 0f; _lifetimeCompleted = false; } } /// /// 检查特效是否正在播放 / Check if VFX is playing /// public bool IsPlaying() { return m_iState == GFX_STATE.ST_PLAY; } /// /// Set lifetime duration /// /// 生命周期时长(秒),-1表示无限 / Lifetime in seconds, -1 for infinite public void SetLifeTime(float lifeTime) { _lifeTime = lifeTime; _elapsedTime = 0f; _lifetimeCompleted = false; } /// /// Get lifetime duration /// public float GetLifeTime() { return _lifeTime; } /// /// Get elapsed time /// public float GetElapsedTime() { return _elapsedTime; } /// /// Get remaining lifetime /// public float GetRemainingLifeTime() { if (_lifeTime <= 0) return -1f; return Mathf.Max(0f, _lifeTime - _elapsedTime); } /// /// Check if lifetime is completed /// public bool IsLifetimeCompleted() { return _lifetimeCompleted; } } }