172 lines
4.2 KiB
C#
172 lines
4.2 KiB
C#
|
using System.Collections.Generic;
|
||
|
using AK.Wwise;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
public class ParticleLifetimeSoundPlayer : MonoBehaviour
|
||
|
{
|
||
|
private class ParticleLifetimeTracker
|
||
|
{
|
||
|
private static int idCounter;
|
||
|
|
||
|
public bool isActive;
|
||
|
|
||
|
private bool firedStart;
|
||
|
|
||
|
private bool firedEnd;
|
||
|
|
||
|
private float lifetimeTimeStamp;
|
||
|
|
||
|
private float startTimeTimeStamp;
|
||
|
|
||
|
private float endTimeTimeStamp;
|
||
|
|
||
|
private int localId;
|
||
|
|
||
|
private AK.Wwise.Event startEvent;
|
||
|
|
||
|
private AK.Wwise.Event endEvent;
|
||
|
|
||
|
private GameObject soundObject;
|
||
|
|
||
|
public ParticleLifetimeTracker(GameObject go)
|
||
|
{
|
||
|
soundObject = go;
|
||
|
}
|
||
|
|
||
|
public void Initialize(float currentTime, float lifeTime, float startTimeOffset, float endTimeOffset, ref AK.Wwise.Event _startEvent, ref AK.Wwise.Event _endEvent, bool debug)
|
||
|
{
|
||
|
localId = idCounter++;
|
||
|
lifetimeTimeStamp = currentTime + lifeTime;
|
||
|
startTimeTimeStamp = currentTime + startTimeOffset;
|
||
|
endTimeTimeStamp = lifetimeTimeStamp + endTimeOffset;
|
||
|
firedStart = false;
|
||
|
firedEnd = false;
|
||
|
isActive = true;
|
||
|
startEvent = _startEvent;
|
||
|
endEvent = _endEvent;
|
||
|
}
|
||
|
|
||
|
public void Update(float currentTime, bool debug)
|
||
|
{
|
||
|
if (isActive)
|
||
|
{
|
||
|
if (!firedStart && currentTime > startTimeTimeStamp)
|
||
|
{
|
||
|
firedStart = true;
|
||
|
startEvent?.Post(soundObject);
|
||
|
}
|
||
|
if (!firedEnd && currentTime > endTimeTimeStamp)
|
||
|
{
|
||
|
firedEnd = true;
|
||
|
endEvent?.Post(soundObject);
|
||
|
}
|
||
|
isActive = currentTime < lifetimeTimeStamp;
|
||
|
_ = !isActive && debug;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public ParticleSystem particleSystemToTrack;
|
||
|
|
||
|
[Tooltip("How long after a particle is born should the StartEvent be posted.")]
|
||
|
public float startTimeOffset;
|
||
|
|
||
|
[Tooltip("How long before/after a particle dies should the EndEvent be posted.")]
|
||
|
public float endTimeOffset;
|
||
|
|
||
|
[Tooltip("Displays a message whenever a new particle is born")]
|
||
|
public bool debugMessages;
|
||
|
|
||
|
public AK.Wwise.Event startEvent;
|
||
|
|
||
|
public AK.Wwise.Event endEvent;
|
||
|
|
||
|
[Tooltip("How long between particles should we wait before firing the next sound. -1 = no delay")]
|
||
|
public float soundCooldown = -1f;
|
||
|
|
||
|
private float lastParticleTrackedTimeStamp;
|
||
|
|
||
|
private ParticleSystem.Particle[] particleArray;
|
||
|
|
||
|
[Space(20f)]
|
||
|
[SerializeField]
|
||
|
public List<GameObject> soundObjects = new List<GameObject>();
|
||
|
|
||
|
private List<ParticleLifetimeTracker> particleTrackers = new List<ParticleLifetimeTracker>();
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
if (particleSystemToTrack == null)
|
||
|
{
|
||
|
particleSystemToTrack = GetComponent<ParticleSystem>();
|
||
|
}
|
||
|
int count = soundObjects.Count;
|
||
|
for (int i = 0; i < count; i++)
|
||
|
{
|
||
|
particleTrackers.Add(new ParticleLifetimeTracker(soundObjects[i]));
|
||
|
}
|
||
|
if (particleSystemToTrack != null)
|
||
|
{
|
||
|
particleArray = new ParticleSystem.Particle[particleSystemToTrack.main.maxParticles];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void LateUpdate()
|
||
|
{
|
||
|
if (particleSystemToTrack == null)
|
||
|
{
|
||
|
base.enabled = false;
|
||
|
return;
|
||
|
}
|
||
|
float time = Time.time;
|
||
|
UpdateExistingParticlePlayers(time);
|
||
|
if (particleSystemToTrack.isEmitting && !(time - lastParticleTrackedTimeStamp < soundCooldown))
|
||
|
{
|
||
|
DiscoverAndTrackNewParticles(time);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void UpdateExistingParticlePlayers(float currentTime)
|
||
|
{
|
||
|
for (int i = 0; i < particleTrackers.Count; i++)
|
||
|
{
|
||
|
particleTrackers[i]?.Update(currentTime, debugMessages);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private ParticleLifetimeTracker FindAvailableParticleTracker()
|
||
|
{
|
||
|
int count = particleTrackers.Count;
|
||
|
for (int i = 0; i < count; i++)
|
||
|
{
|
||
|
if (!particleTrackers[i].isActive)
|
||
|
{
|
||
|
return particleTrackers[i];
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private void DiscoverAndTrackNewParticles(float currentTime)
|
||
|
{
|
||
|
ParticleLifetimeTracker particleLifetimeTracker = FindAvailableParticleTracker();
|
||
|
if (particleLifetimeTracker == null)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
int particles = particleSystemToTrack.GetParticles(particleArray);
|
||
|
for (int i = 0; i < particles; i++)
|
||
|
{
|
||
|
ParticleSystem.Particle particle = particleArray[i];
|
||
|
if (Mathf.Approximately(particle.startLifetime, particle.remainingLifetime))
|
||
|
{
|
||
|
lastParticleTrackedTimeStamp = currentTime;
|
||
|
particleLifetimeTracker.Initialize(currentTime, particle.remainingLifetime, startTimeOffset, endTimeOffset, ref startEvent, ref endEvent, debugMessages);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|