void DrawDebugPath() { if (_los) { Debug.DrawLine(_sourceTransform.position, _listenerTransform.position, Color.red); } else { Color lineColor = Color.red; if (_nearestNodeToListener != null) { Debug.DrawLine(_listenerTransform.position, _nearestNodeToListener.position, lineColor); } Node currentNode = _nearestNodeToListener; while (currentNode != null && _transientNodes.ContainsKey(currentNode)) { TransientNode tNode = _transientNodes[currentNode]; Node parentNode = tNode.parent; if (parentNode != null) { Debug.DrawLine(currentNode.position, parentNode.position, lineColor); } else { Debug.DrawLine(currentNode.position, _sourceTransform.position, lineColor); } currentNode = parentNode; } } }
void UpdateAudioSettings() { // Find nearest node to listener. _nearestNodeToListener = NearestNodeInLOS(_listenerTransform.position); if (_nearestNodeToListener == null) { Debug.Log("[Propagate] No PropagateNodes in line of sight of listener."); _nearestNodeToListener = NearestNode(_listenerTransform.position); if (_nearestNodeToListener == null) { Debug.LogError("[Propagate] No PropagateNodes near listener. Falling back to standard audio source."); audioSource.volume = 1.0f; this.enabled = false; return; } } // Find the last visible node along the path. Node currentNode = _nearestNodeToListener; while (currentNode != null && _transientNodes.ContainsKey(currentNode)) { TransientNode tNode = _transientNodes[currentNode]; if (tNode.parent != null) { if (CheckLOSToNode(tNode.parent, _listenerTransform.position)) { _nearestNodeToListener = tNode.parent; } else { break; } } currentNode = tNode.parent; } if (drawDebugPath) { //Debug.DrawLine(_listenerTransform.position, _nearestNodeToListener.position, Color.red); } TransientNode nearestTNodeToListener; bool didGetNearestNode = _transientNodes.TryGetValue(_nearestNodeToListener, out nearestTNodeToListener); if (!didGetNearestNode) { Debug.LogError("[Propagate] No node near to listener."); } // Add the distance from last node to listener. float nodeListenerDist = Vector3.Distance(_nearestNodeToListener.position, _listenerTransform.position); float totalDistance = nearestTNodeToListener.distanceToSource + nodeListenerDist; // Move the audio source. _perceivedPosition = Vector3.Lerp(_sourceTransform.position, _nearestNodeToListener.position, profile.percievedPositionEffect); Vector3 listenerNodeDirection = (_perceivedPosition - _listenerTransform.position).normalized; _perceivedPosition = _listenerTransform.position + (listenerNodeDirection * totalDistance); // Calculate the lowpass. float maxAngle = profile.frequencySettings.maxAngle; float normalizedAngle = RemapFloat(nearestTNodeToListener.curvatureToSource * Mathf.Rad2Deg, 0f, maxAngle, 0f, 1f); float normalizedFrequency = profile.frequencySettings.curve.Evaluate(normalizedAngle); _cutoffFrequency = RemapFloat(normalizedFrequency, 0f, 1f, profile.frequencySettings.minCutoff, profile.frequencySettings.maxCutoff); // Calculate volume reduction due to blocked LOS. _volume = 1.0f; RaycastHit hitInfo; if (Physics.Linecast(_listenerTransform.position, _nearestNodeToListener.position, out hitInfo) && !hitInfo.collider.CompareTag("Player")) { AudioOccluder occluder = hitInfo.collider.GetComponent <AudioOccluder>(); if (occluder != null) { _volume *= 1f - occluder.volumeReduction; _cutoffFrequency *= 1f - occluder.frequencyReduction; } else { _volume *= 1f - profile.occlusionSettings.volumeReduction; _cutoffFrequency *= 1f - profile.occlusionSettings.frequencyReduction; } } currentNode = _nearestNodeToListener; while (currentNode != null && _transientNodes.ContainsKey(currentNode)) { TransientNode tNode = _transientNodes[currentNode]; if (tNode.parent != null && Physics.Linecast(currentNode.position, tNode.parent.position, out hitInfo)) { AudioOccluder occluder = hitInfo.collider.GetComponent <AudioOccluder>(); if (occluder != null) { _volume *= 1f - occluder.volumeReduction; _cutoffFrequency *= 1f - occluder.frequencyReduction; } else { _volume *= 1f - profile.occlusionSettings.volumeReduction; _cutoffFrequency *= 1f - profile.occlusionSettings.frequencyReduction; } } currentNode = tNode.parent; } }
void Propagate() { _transientNodes.Clear(); var openNodes = new List <Node>(); // Find nearest node. Node nearestNode = NearestNodeInLOS(_sourceTransform.position); if (nearestNode == null) { Debug.LogError("[Propagate] Could not find PropagateNode in line of sight to audio source. Falling back to standard Audio Source."); audioSource.volume = 1.0f; this.enabled = false; return; } Node currentNode = nearestNode; _transientNodes[currentNode] = new TransientNode() { parent = null }; while (currentNode != null) { TransientNode tNode = _transientNodes[currentNode]; if (tNode.parent != null) { TransientNode parentTNode = _transientNodes[tNode.parent]; tNode.distanceToSource = parentTNode.distanceToSource + Vector3.Distance(tNode.parent.position, currentNode.position); tNode.direction = Quaternion.Euler((currentNode.position - tNode.parent.position).normalized); tNode.curvatureToSource = parentTNode.curvatureToSource + Quaternion.Angle(parentTNode.direction, tNode.direction); } else { tNode.distanceToSource = Vector3.Distance(currentNode.position, _sourceTransform.position); tNode.curvatureToSource = 0; tNode.direction = Quaternion.identity; tNode.parent = null; } _transientNodes[currentNode] = tNode; foreach (var connectedNode in currentNode.connections) { if (!_transientNodes.ContainsKey(connectedNode) && !openNodes.Contains(connectedNode)) { openNodes.Add(connectedNode); _transientNodes[connectedNode] = new TransientNode() { parent = currentNode }; } } if (openNodes.Count > 0) { currentNode = openNodes[0]; openNodes.RemoveAt(0); } else { currentNode = null; } } }