swb_base/WeaponParticleManager.cs

Component placed in the scene root that tracks spawned weapon particles and decals. It keeps two queues (ejectParticles and decals), enforces maximum counts by destroying the oldest GameObject when limits are exceeded, and exposes synced properties for MaxDecals and MaxEject.

using System.Collections.Generic;

namespace SWB.Base;

/// <summary>
/// Attach this component somewhere in the root of your scene.
/// Manages particle spawning
/// </summary>
[Group( "SWB" )]
[Title( "Weapon Particle Settings" )]
public class WeaponParticleManager : Component
{
	public static WeaponParticleManager Instance { get; private set; }

	/// <summary>Max total decals allowed at the same time</summary>
	[Sync( SyncFlags.FromHost ), Property] public int MaxDecals { get; set; } = 30;

	/// <summary>Max total eject particles allowed at the same time</summary>
	[Sync( SyncFlags.FromHost ), Property] public int MaxEject { get; set; } = 180;

	private Queue<GameObject> ejectParticles = new();
	private Queue<GameObject> decals = new();

	protected override void OnDestroy()
	{
		if ( Instance == this )
			Instance = null;
	}

	protected override void OnAwake()
	{
		Instance = this;
	}

	private void AddToQueue( GameObject particle, Queue<GameObject> queue, int max )
	{
		// Add to queue
		queue.Enqueue( particle );

		if ( queue.Count > max )
		{
			var oldest = queue.Dequeue();
			if ( oldest.IsValid() )
				oldest.Destroy();
		}
	}

	public void AddEject( GameObject particle, bool parent = true )
	{
		AddToQueue( particle, ejectParticles, MaxEject );

		if ( parent )
			particle.SetParent( this.GameObject );
	}

	public void AddDecal( GameObject decal, bool parent = true )
	{
		AddToQueue( decal, decals, MaxDecals );

		if ( parent )
			decal.SetParent( this.GameObject );
	}
}