sea-battle-vr/Assets/Scripts/Gameplay/ReplicasSystem.cs

112 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}