private void UpdateOcclusion() { var hasOcclusionOn = GrpVariation.UsesOcclusion; if (!hasOcclusionOn) { if (!_occlusionOnLastFrame) { return; } _occlusionOnLastFrame = false; MasterAudio.StopTrackingOcclusionForSource(GrpVariation.GameObj); ResetToNonOcclusionSetting(); return; } _occlusionOnLastFrame = true; if (_listenerThisFrame == null) { // cannot occlude without something to raycast at. return; } if (Time.realtimeSinceStartup - _occlusionLastCalculated <= MasterAudio.ReOccludeCheckTime) { // too early, abort and try next frame return; } var lastCalcTime = Time.realtimeSinceStartup; if (_occlusionLastCalculated == FakeNegativeFloatValue) { // spread out the line casts so they're not all on the same frame (for ambient sounds that all start in the Scene). lastCalcTime += MasterAudio.ReOccludeCheckTime * Random.Range(0f, 0.9f); } _occlusionLastCalculated = lastCalcTime; var direction = _listenerThisFrame.position - Trans.position; var distanceToListener = direction.magnitude; if (distanceToListener > VarAudio.maxDistance) { // out of hearing range, no reason to calculate occlusion. MasterAudio.AddToOcclusionOutOfRangeSources(GrpVariation.GameObj); ResetToNonOcclusionSetting(); return; } MasterAudio.AddToOcclusionInRangeSources(GrpVariation.GameObj); if (GrpVariation.LowPassFilter == null) { // in case Occlusion got turned on during runtime. GrpVariation.gameObject.AddComponent <AudioLowPassFilter>(); } #if UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 #else var is2DRaycast = _maThisFrame.occlusionRaycastMode == MasterAudio.RaycastMode.Physics2D; var oldQueriesStart = Physics2D.queriesStartInColliders; if (is2DRaycast) { Physics2D.queriesStartInColliders = _maThisFrame.occlusionIncludeStartRaycast2DCollider; } #endif var hitPoint = Vector3.zero; float?hitDistance = null; var isHit = false; if (_maThisFrame.occlusionUseLayerMask) { switch (_maThisFrame.occlusionRaycastMode) { case MasterAudio.RaycastMode.Physics3D: RaycastHit hitObject; if (Physics.Raycast(Trans.position, direction, out hitObject, distanceToListener, _maThisFrame.occlusionLayerMask.value)) { isHit = true; hitPoint = hitObject.point; hitDistance = hitObject.distance; } break; case MasterAudio.RaycastMode.Physics2D: var castHit2D = Physics2D.Raycast(Trans.position, direction, distanceToListener, _maThisFrame.occlusionLayerMask.value); if (castHit2D.transform != null) { isHit = true; hitPoint = castHit2D.point; hitDistance = castHit2D.distance; } break; } } else { switch (_maThisFrame.occlusionRaycastMode) { case MasterAudio.RaycastMode.Physics3D: RaycastHit hitObject; if (Physics.Raycast(Trans.position, direction, out hitObject, distanceToListener)) { isHit = true; hitPoint = hitObject.point; hitDistance = hitObject.distance; } break; case MasterAudio.RaycastMode.Physics2D: var castHit2D = Physics2D.Raycast(Trans.position, direction, distanceToListener); if (castHit2D.transform != null) { isHit = true; hitPoint = castHit2D.point; hitDistance = castHit2D.distance; } break; } } #if UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 #else if (is2DRaycast) { Physics2D.queriesStartInColliders = oldQueriesStart; } #endif var endPoint = isHit ? hitPoint : _listenerThisFrame.position; var lineColor = isHit ? Color.red : Color.green; if (_maThisFrame.occlusionShowRaycasts) { Debug.DrawLine(Trans.position, endPoint, lineColor, .1f); } if (!isHit) { // ReSharper disable once PossibleNullReferenceException MasterAudio.RemoveFromBlockedOcclusionSources(GrpVariation.GameObj); ResetToNonOcclusionSetting(); return; } MasterAudio.AddToBlockedOcclusionSources(GrpVariation.GameObj); var ratioToEdgeOfSound = hitDistance.Value / VarAudio.maxDistance; var filterFrequency = AudioUtil.GetOcclusionCutoffFrequencyByDistanceRatio(ratioToEdgeOfSound); // ReSharper disable once PossibleNullReferenceException GrpVariation.LowPassFilter.cutoffFrequency = filterFrequency; }
/// <summary> /// This method is called in a batch from ListenerFollower /// </summary> /// <returns></returns> public bool RayCastForOcclusion() { DoneWithOcclusion(); var raycastOrigin = Trans.position; var offset = RayCastOriginOffset; if (offset > 0) { raycastOrigin = Vector3.MoveTowards(raycastOrigin, _listenerThisFrame.position, offset); } var direction = _listenerThisFrame.position - raycastOrigin; var distanceToListener = direction.magnitude; if (distanceToListener > VarAudio.maxDistance) { // out of hearing range, no reason to calculate occlusion. MasterAudio.AddToOcclusionOutOfRangeSources(GrpVariation.GameObj); ResetToNonOcclusionSetting(); return(false); } MasterAudio.AddToOcclusionInRangeSources(GrpVariation.GameObj); var is2DRaycast = _maThisFrame.occlusionRaycastMode == MasterAudio.RaycastMode.Physics2D; if (GrpVariation.LowPassFilter == null) { // in case Occlusion got turned on during runtime. var newFilter = GrpVariation.gameObject.AddComponent <AudioLowPassFilter>(); GrpVariation.LowPassFilter = newFilter; } var oldQueriesStart = Physics2D.queriesStartInColliders; if (is2DRaycast) { Physics2D.queriesStartInColliders = _maThisFrame.occlusionIncludeStartRaycast2DCollider; } var oldRaycastsHitTriggers = true; // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (is2DRaycast) { oldRaycastsHitTriggers = Physics2D.queriesHitTriggers; Physics2D.queriesHitTriggers = _maThisFrame.occlusionRaycastsHitTriggers; } else { oldRaycastsHitTriggers = Physics.queriesHitTriggers; Physics.queriesHitTriggers = _maThisFrame.occlusionRaycastsHitTriggers; } var hitPoint = Vector3.zero; float?hitDistance = null; var isHit = false; if (_maThisFrame.occlusionUseLayerMask) { switch (_maThisFrame.occlusionRaycastMode) { case MasterAudio.RaycastMode.Physics3D: RaycastHit hitObject; if (Physics.Raycast(raycastOrigin, direction, out hitObject, distanceToListener, _maThisFrame.occlusionLayerMask.value)) { isHit = true; hitPoint = hitObject.point; hitDistance = hitObject.distance; } break; case MasterAudio.RaycastMode.Physics2D: var castHit2D = Physics2D.Raycast(raycastOrigin, direction, distanceToListener, _maThisFrame.occlusionLayerMask.value); if (castHit2D.transform != null) { isHit = true; hitPoint = castHit2D.point; hitDistance = castHit2D.distance; } break; } } else { switch (_maThisFrame.occlusionRaycastMode) { case MasterAudio.RaycastMode.Physics3D: RaycastHit hitObject; if (Physics.Raycast(raycastOrigin, direction, out hitObject, distanceToListener)) { isHit = true; hitPoint = hitObject.point; hitDistance = hitObject.distance; } break; case MasterAudio.RaycastMode.Physics2D: var castHit2D = Physics2D.Raycast(raycastOrigin, direction, distanceToListener); if (castHit2D.transform != null) { isHit = true; hitPoint = castHit2D.point; hitDistance = castHit2D.distance; } break; } } if (is2DRaycast) { Physics2D.queriesStartInColliders = oldQueriesStart; Physics2D.queriesHitTriggers = oldRaycastsHitTriggers; } else { Physics.queriesHitTriggers = oldRaycastsHitTriggers; } if (_maThisFrame.occlusionShowRaycasts) { var endPoint = isHit ? hitPoint : _listenerThisFrame.position; var lineColor = isHit ? Color.red : Color.green; Debug.DrawLine(raycastOrigin, endPoint, lineColor, .1f); } if (!isHit) { // ReSharper disable once PossibleNullReferenceException MasterAudio.RemoveFromBlockedOcclusionSources(GrpVariation.GameObj); ResetToNonOcclusionSetting(); return(true); } MasterAudio.AddToBlockedOcclusionSources(GrpVariation.GameObj); var ratioToEdgeOfSound = hitDistance.Value / VarAudio.maxDistance; var filterFrequency = AudioUtil.GetOcclusionCutoffFrequencyByDistanceRatio(ratioToEdgeOfSound, this); var fadeTime = _maThisFrame.occlusionFreqChangeSeconds; if (fadeTime <= MasterAudio.InnerLoopCheckInterval) // fast, just do it instantly. // ReSharper disable once PossibleNullReferenceException { GrpVariation.LowPassFilter.cutoffFrequency = filterFrequency; return(true); } MasterAudio.GradualOcclusionFreqChange(GrpVariation, fadeTime, filterFrequency); return(true); }