using UnityEngine; using Cysharp.Threading.Tasks; using System.Threading; using System; using System.Collections.Concurrent; public class ReplicasPlayer : MonoBehaviour { [SerializeField] float delay = 0.5f; private bool initialized = false; private ConcurrentQueue replicas; public void Init() { if (initialized) { Debug.LogWarning("Попытка повторной инициализации системы", this); return; } replicas = new ConcurrentQueue(); var token = this.GetCancellationTokenOnDestroy(); Process(token).Forget(); initialized = true; } public void EnqueueReplica(Replica replica) { if (!initialized) return; var handledReplica = replica; if (handledReplica.clip == null) return; if (UnityEngine.Random.Range(0f, 1f) >= handledReplica.probability) return; if (handledReplica.playParallel) { Debug.Log("исполняю"); SoundManager.PlayReplica(handledReplica.clip); return; } handledReplica.creationTime = Time.time; replicas.Enqueue(handledReplica); } public void EnqueueReplica(ReplicasSequence replicas) => EnqueueReplica(replicas.GetRandomReplica()); private async UniTask Process(CancellationToken token) { while (!token.IsCancellationRequested) { if (replicas.TryDequeue(out Replica replica)) { bool replicaIsFresh = Time.time - replica.creationTime <= replica.lifetime; if (replicaIsFresh) { SoundManager.PlayReplica(replica.clip); await UniTask.Delay(TimeSpan.FromSeconds(replica.clip.length + delay), cancellationToken: token); continue; } } await UniTask.Yield(); } } }