112 lines
3.1 KiB
C#
112 lines
3.1 KiB
C#
using UnityEngine;
|
||
using Cysharp.Threading.Tasks;
|
||
using System.Threading;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
|
||
public class ReplicasSystem : MonoBehaviour
|
||
{
|
||
[SerializeField] AudioSource audioSource;
|
||
[SerializeField] float delay = 0.5f;
|
||
|
||
private bool initialized = false;
|
||
private ConcurrentQueue<Replica> replicas;
|
||
|
||
public void Init()
|
||
{
|
||
if (initialized)
|
||
{
|
||
Debug.LogWarning("Попытка повторной инициализации системы", this);
|
||
return;
|
||
}
|
||
|
||
if (audioSource == null)
|
||
{
|
||
Debug.LogError("Не установлен AudioSource", this);
|
||
return;
|
||
}
|
||
|
||
replicas = new ConcurrentQueue<Replica>();
|
||
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)
|
||
{
|
||
audioSource.PlayOneShot(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)
|
||
{
|
||
audioSource.PlayOneShot(replica.clip);
|
||
await UniTask.Delay(TimeSpan.FromSeconds(replica.clip.length + delay), cancellationToken: token);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
await UniTask.Yield();
|
||
}
|
||
}
|
||
|
||
[Serializable]
|
||
public struct Replica
|
||
{
|
||
public AudioClip clip;
|
||
public float lifetime;
|
||
public bool playParallel;
|
||
[Range(0,1)] public float probability;
|
||
|
||
[HideInInspector] public float creationTime;
|
||
}
|
||
|
||
[Serializable]
|
||
public struct ReplicasSequence // для набора однообразных реплик
|
||
{
|
||
public List<AudioClip> clips;
|
||
public float lifetime;
|
||
public bool playParallel;
|
||
[Range(0, 1)] public float probability;
|
||
|
||
public Replica GetRandomReplica()
|
||
{
|
||
if(clips == null || clips.Count == 0) return default(Replica);
|
||
var clip = clips[UnityEngine.Random.Range(0, clips.Count)];
|
||
|
||
var replica = new Replica();
|
||
replica.clip = clip;
|
||
replica.lifetime = lifetime;
|
||
replica.playParallel = playParallel;
|
||
replica.probability = probability;
|
||
|
||
return replica;
|
||
}
|
||
}
|
||
} |