165 lines
5.5 KiB
C#
165 lines
5.5 KiB
C#
using UnityEngine;
|
|
using FMODUnity;
|
|
using FMOD.Studio;
|
|
using System.Collections;
|
|
|
|
public class FirstPersonOcclusion : MonoBehaviour
|
|
{
|
|
[Header("FMOD Event")]
|
|
[SerializeField] private EventReference SelectAudio;
|
|
|
|
private EventInstance AudioOccluded;
|
|
private EventDescription AudioDes;
|
|
private StudioListener Listener;
|
|
private PLAYBACK_STATE pb;
|
|
|
|
[Header("Occlusion Options")]
|
|
[SerializeField][Range(0f, 10f)] private float SoundOcclusionWidening = 1f;
|
|
[SerializeField][Range(0f, 10f)] private float PlayerOcclusionWidening = 1f;
|
|
[SerializeField] private LayerMask OcclusionLayer;
|
|
|
|
private bool AudioIsVirtual;
|
|
private float MaxDistance;
|
|
private float ListenerDistance;
|
|
private float lineCastHitCount = 0f;
|
|
private Color colour;
|
|
|
|
private bool initialisedExternally = false;
|
|
|
|
// ============================================================
|
|
// NEW — Optional external initialiser
|
|
// ============================================================
|
|
public void InitialiseWithInstance(EventInstance instance)
|
|
{
|
|
AudioOccluded = instance;
|
|
initialisedExternally = true;
|
|
|
|
RuntimeManager.AttachInstanceToGameObject(
|
|
AudioOccluded,
|
|
gameObject,
|
|
GetComponent<Rigidbody>()
|
|
);
|
|
|
|
AudioOccluded.getDescription(out AudioDes);
|
|
AudioDes.getMinMaxDistance(out float min, out MaxDistance);
|
|
}
|
|
|
|
// ============================================================
|
|
// ORIGINAL START — kept exactly the same unless external init used
|
|
// ============================================================
|
|
private IEnumerator Start()
|
|
{
|
|
// If already initialised, skip internal creation
|
|
if (!initialisedExternally)
|
|
{
|
|
AudioOccluded = RuntimeManager.CreateInstance(SelectAudio);
|
|
RuntimeManager.AttachInstanceToGameObject(AudioOccluded, gameObject);
|
|
AudioOccluded.start();
|
|
AudioOccluded.release();
|
|
|
|
AudioDes = RuntimeManager.GetEventDescription(SelectAudio);
|
|
AudioDes.getMinMaxDistance(out float minDistance, out MaxDistance);
|
|
}
|
|
|
|
// Find listener (kept exactly as before)
|
|
yield return new WaitUntil(() => FindObjectOfType<StudioListener>() != null);
|
|
Listener = FindObjectOfType<StudioListener>();
|
|
}
|
|
|
|
// ============================================================
|
|
// UNCHANGED core functionality
|
|
// ============================================================
|
|
private void FixedUpdate()
|
|
{
|
|
if (Listener == null) return;
|
|
|
|
AudioOccluded.isVirtual(out AudioIsVirtual);
|
|
AudioOccluded.getPlaybackState(out pb);
|
|
ListenerDistance = Vector3.Distance(transform.position, Listener.transform.position);
|
|
|
|
if (!AudioIsVirtual && pb == PLAYBACK_STATE.PLAYING && ListenerDistance <= MaxDistance)
|
|
{
|
|
OccludeBetween(transform.position, Listener.transform.position);
|
|
}
|
|
|
|
lineCastHitCount = 0f;
|
|
}
|
|
|
|
private void OccludeBetween(Vector3 sound, Vector3 listener)
|
|
{
|
|
Vector3 SoundLeft = CalculatePoint(sound, listener, SoundOcclusionWidening, true);
|
|
Vector3 SoundRight = CalculatePoint(sound, listener, SoundOcclusionWidening, false);
|
|
|
|
Vector3 ListenerLeft = CalculatePoint(listener, sound, PlayerOcclusionWidening, true);
|
|
Vector3 ListenerRight = CalculatePoint(listener, sound, PlayerOcclusionWidening, false);
|
|
|
|
Vector3 SoundAbove = new Vector3(sound.x, sound.y + SoundOcclusionWidening, sound.z);
|
|
Vector3 SoundBelow = new Vector3(sound.x, sound.y - SoundOcclusionWidening, sound.z);
|
|
Vector3 ListenerAbove = new Vector3(listener.x, listener.y + PlayerOcclusionWidening * .5f, listener.z);
|
|
Vector3 ListenerBelow = new Vector3(listener.x, listener.y - PlayerOcclusionWidening * .5f, listener.z);
|
|
|
|
CastLine(SoundLeft, ListenerLeft);
|
|
CastLine(SoundLeft, listener);
|
|
CastLine(SoundLeft, ListenerRight);
|
|
|
|
CastLine(sound, ListenerLeft);
|
|
CastLine(sound, listener);
|
|
CastLine(sound, ListenerRight);
|
|
|
|
CastLine(SoundRight, ListenerLeft);
|
|
CastLine(SoundRight, listener);
|
|
CastLine(SoundRight, ListenerRight);
|
|
|
|
CastLine(SoundAbove, ListenerAbove);
|
|
CastLine(SoundBelow, ListenerBelow);
|
|
|
|
colour = (PlayerOcclusionWidening == 0f || SoundOcclusionWidening == 0f) ? Color.blue : Color.green;
|
|
|
|
SetParameter();
|
|
}
|
|
|
|
private Vector3 CalculatePoint(Vector3 a, Vector3 b, float m, bool posOrneg)
|
|
{
|
|
float n = Vector3.Distance(new Vector3(a.x, 0f, a.z), new Vector3(b.x, 0f, b.z));
|
|
if (n == 0f) return a;
|
|
|
|
float mn = (m / n);
|
|
float x, z;
|
|
|
|
if (posOrneg)
|
|
{
|
|
x = a.x + (mn * (a.z - b.z));
|
|
z = a.z - (mn * (a.x - b.x));
|
|
}
|
|
else
|
|
{
|
|
x = a.x - (mn * (a.z - b.z));
|
|
z = a.z + (mn * (a.x - b.x));
|
|
}
|
|
|
|
return new Vector3(x, a.y, z);
|
|
}
|
|
|
|
private void CastLine(Vector3 Start, Vector3 End)
|
|
{
|
|
RaycastHit hit;
|
|
bool isHit = Physics.Linecast(Start, End, out hit, OcclusionLayer);
|
|
|
|
if (isHit)
|
|
{
|
|
lineCastHitCount++;
|
|
//Debug.DrawLine(Start, End, Color.red);
|
|
}
|
|
else
|
|
{
|
|
//Debug.DrawLine(Start, End, colour);
|
|
}
|
|
}
|
|
|
|
private void SetParameter()
|
|
{
|
|
float occlusionValue = lineCastHitCount / 11;
|
|
AudioOccluded.setParameterByName("Occlusion", occlusionValue);
|
|
}
|
|
}
|