Files
test/Assets/PerfectWorld/Scripts/Vfx/BaseVfxObject.cs
T
2025-12-08 09:48:37 +07:00

308 lines
7.7 KiB
C#

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;
/// <summary>
/// 生命周期完成事件 / Event triggered when lifetime is completed
/// </summary>
public event Action OnLifetimeCompleted;
private void Awake()
{
if (_vfx == null)
{
_vfx = GetComponent<ParticleSystem>();
}
if (_vfx != null)
{
_originalScale = _vfx.transform.localScale;
}
}
private void OnDestroy()
{
if(!string.IsNullOrEmpty(_vfxPath))
{
AddressableManager.Instance.ReleaseAsset(_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
/// <summary>
/// Set VFX scale
/// </summary>
public void SetScale(float scale)
{
SetScale(new Vector3(scale, scale, scale));
}
/// <summary>
/// Set VFX scale with vector
/// </summary>
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);
}
}
/// <summary>
/// Set VFX offset
/// </summary>
public void SetOffset(Vector3 offset)
{
_offset = offset;
if (_vfx != null)
{
_vfx.transform.localPosition = offset;
}
}
/// <summary>
/// Set VFX world position
/// </summary>
public void SetPosition(Vector3 position)
{
if (_vfx != null)
{
_vfx.transform.position = position;
}
}
/// <summary>
/// Set VFX rotation
/// </summary>
public void SetRotation(Quaternion rotation)
{
if (_vfx != null)
{
_vfx.transform.rotation = rotation;
}
}
/// <summary>
/// Set VFX rotation with euler angles
/// </summary>
public void SetRotation(Vector3 eulerAngles)
{
SetRotation(Quaternion.Euler(eulerAngles));
}
/// <summary>
/// Set VFX color
/// </summary>
public void SetColor(Color color)
{
if (_vfx != null)
{
var main = _vfx.main;
main.startColor = color;
}
}
/// <summary>
/// Set VFX duration
/// </summary>
public void SetDuration(float duration)
{
if (_vfx != null)
{
var main = _vfx.main;
main.duration = duration;
}
}
/// <summary>
/// Set VFX playback speed
/// </summary>
public void SetSpeed(float speed)
{
if (_vfx != null)
{
var main = _vfx.main;
main.simulationSpeed = speed;
}
}
/// <summary>
/// Play VFX
/// </summary>
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;
}
}
/// <summary>
/// Stop VFX
/// </summary>
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;
}
}
/// <summary>
/// Pause VFX
/// </summary>
public void Pause()
{
if (_vfx != null)
{
m_iState = GFX_STATE.ST_PAUSE;
_vfx.Pause();
}
}
/// <summary>
/// Clear all VFX particles
/// </summary>
public void Clear()
{
if (_vfx != null)
{
_vfx.Clear();
}
}
/// <summary>
/// 重新开始播放 / Restart VFX
/// </summary>
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;
}
}
/// <summary>
/// 检查特效是否正在播放 / Check if VFX is playing
/// </summary>
public bool IsPlaying()
{
return m_iState == GFX_STATE.ST_PLAY;
}
/// <summary>
/// Set lifetime duration
/// </summary>
/// <param name="lifeTime">生命周期时长(秒),-1表示无限 / Lifetime in seconds, -1 for infinite</param>
public void SetLifeTime(float lifeTime)
{
_lifeTime = lifeTime;
_elapsedTime = 0f;
_lifetimeCompleted = false;
}
/// <summary>
/// Get lifetime duration
/// </summary>
public float GetLifeTime()
{
return _lifeTime;
}
/// <summary>
/// Get elapsed time
/// </summary>
public float GetElapsedTime()
{
return _elapsedTime;
}
/// <summary>
/// Get remaining lifetime
/// </summary>
public float GetRemainingLifeTime()
{
if (_lifeTime <= 0)
return -1f;
return Mathf.Max(0f, _lifeTime - _elapsedTime);
}
/// <summary>
/// Check if lifetime is completed
/// </summary>
public bool IsLifetimeCompleted()
{
return _lifetimeCompleted;
}
}
}