From ee492f29ab7344f5a64379f9024baaac1c4d32a9 Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Sat, 3 Aug 2024 00:29:30 +0200 Subject: [PATCH 1/4] CanHearTarget: make sure no obstacle is static Instead of checking if first one is not --- Assets/Scripts/Game/EnemySenses.cs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Assets/Scripts/Game/EnemySenses.cs b/Assets/Scripts/Game/EnemySenses.cs index b643862fe0..c4b3c9e525 100644 --- a/Assets/Scripts/Game/EnemySenses.cs +++ b/Assets/Scripts/Game/EnemySenses.cs @@ -923,24 +923,30 @@ bool CanSeeTarget(DaggerfallEntityBehaviour target) return seen; } + readonly int defaultLayerOnlyMask = 1 << LayerMask.NameToLayer("Default"); + bool CanHearTarget() { float hearingScale = 1f; - // If something is between enemy and target then return false (was reduce hearingScale by half), to minimize - // enemies walking against walls. - // Hearing is not impeded by doors or other non-static objects - RaycastHit hit; - Ray ray = new Ray(transform.position, directionToTarget); - if (Physics.Raycast(ray, out hit)) + // TODO: Modify this by how much noise the target is making + if (distanceToTarget < (HearingRadius * hearingScale) + mobile.Enemy.HearingModifier) { - //DaggerfallEntityBehaviour entity = hit.transform.gameObject.GetComponent(); - if (GameObjectHelper.IsStaticGeometry(hit.transform.gameObject)) - return false; + // If something is between enemy and target then return false (was reduce hearingScale by half), to minimize + // enemies walking against walls. + // Hearing is not impeded by doors or other non-static objects + Ray ray = new Ray(transform.position, directionToTarget); + RaycastHit[] hits = Physics.RaycastAll(ray, distanceToTarget); // , defaultLayerOnlyMask + foreach (RaycastHit hit in hits) + { + //DaggerfallEntityBehaviour entity = hit.transform.gameObject.GetComponent(); + if (GameObjectHelper.IsStaticGeometry(hit.transform.gameObject)) + return false; + } + return true; } - // TODO: Modify this by how much noise the target is making - return distanceToTarget < (HearingRadius * hearingScale) + mobile.Enemy.HearingModifier; + return false; } #endregion From 28fcaea9f536ddb727996e2027dd9d24acc068ec Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Sat, 3 Aug 2024 00:58:12 +0200 Subject: [PATCH 2/4] CanHearTarget: layer mask --- Assets/Scripts/Game/EnemySenses.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Game/EnemySenses.cs b/Assets/Scripts/Game/EnemySenses.cs index c4b3c9e525..3b2d24a93a 100644 --- a/Assets/Scripts/Game/EnemySenses.cs +++ b/Assets/Scripts/Game/EnemySenses.cs @@ -923,12 +923,15 @@ bool CanSeeTarget(DaggerfallEntityBehaviour target) return seen; } - readonly int defaultLayerOnlyMask = 1 << LayerMask.NameToLayer("Default"); + int defaultLayerOnlyMask = 0; bool CanHearTarget() { float hearingScale = 1f; + if (defaultLayerOnlyMask == 0) + defaultLayerOnlyMask = 1 << LayerMask.NameToLayer("Default"); + // TODO: Modify this by how much noise the target is making if (distanceToTarget < (HearingRadius * hearingScale) + mobile.Enemy.HearingModifier) { @@ -936,7 +939,7 @@ bool CanHearTarget() // enemies walking against walls. // Hearing is not impeded by doors or other non-static objects Ray ray = new Ray(transform.position, directionToTarget); - RaycastHit[] hits = Physics.RaycastAll(ray, distanceToTarget); // , defaultLayerOnlyMask + RaycastHit[] hits = Physics.RaycastAll(ray, distanceToTarget, defaultLayerOnlyMask); foreach (RaycastHit hit in hits) { //DaggerfallEntityBehaviour entity = hit.transform.gameObject.GetComponent(); From eece9dbe669aca5b684b5652f155a8d28d345f49 Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Sat, 3 Aug 2024 01:56:46 +0200 Subject: [PATCH 3/4] Optimizations Reuse hits buffer --- Assets/Scripts/Game/EnemySenses.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Assets/Scripts/Game/EnemySenses.cs b/Assets/Scripts/Game/EnemySenses.cs index 3b2d24a93a..7d6b3d0aa9 100644 --- a/Assets/Scripts/Game/EnemySenses.cs +++ b/Assets/Scripts/Game/EnemySenses.cs @@ -923,7 +923,8 @@ bool CanSeeTarget(DaggerfallEntityBehaviour target) return seen; } - int defaultLayerOnlyMask = 0; + private static int defaultLayerOnlyMask = 0; + private static RaycastHit[] hitsBuffer = new RaycastHit[4]; bool CanHearTarget() { @@ -939,11 +940,18 @@ bool CanHearTarget() // enemies walking against walls. // Hearing is not impeded by doors or other non-static objects Ray ray = new Ray(transform.position, directionToTarget); - RaycastHit[] hits = Physics.RaycastAll(ray, distanceToTarget, defaultLayerOnlyMask); - foreach (RaycastHit hit in hits) + int nhits; + while (true) { + nhits = Physics.RaycastNonAlloc(ray, hitsBuffer, distanceToTarget, defaultLayerOnlyMask); + if (nhits < hitsBuffer.Length) + break; + // hitsBuffer may have overflowed, retry with a larger buffer + hitsBuffer = new RaycastHit[nhits + 1]; + }; + for (int i = 0; i < nhits; i++) { //DaggerfallEntityBehaviour entity = hit.transform.gameObject.GetComponent(); - if (GameObjectHelper.IsStaticGeometry(hit.transform.gameObject)) + if (GameObjectHelper.IsStaticGeometry(hitsBuffer[i].transform.gameObject)) return false; } return true; From ac0f377f19dbab4d7c6a819f20da0f14a7cbe4b7 Mon Sep 17 00:00:00 2001 From: Pierre Etchemaite Date: Mon, 7 Oct 2024 00:08:20 +0200 Subject: [PATCH 4/4] Increase raycast buffer size geometrically --- Assets/Scripts/Game/EnemySenses.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/Game/EnemySenses.cs b/Assets/Scripts/Game/EnemySenses.cs index 7d6b3d0aa9..a2fcd18daa 100644 --- a/Assets/Scripts/Game/EnemySenses.cs +++ b/Assets/Scripts/Game/EnemySenses.cs @@ -946,7 +946,7 @@ bool CanHearTarget() if (nhits < hitsBuffer.Length) break; // hitsBuffer may have overflowed, retry with a larger buffer - hitsBuffer = new RaycastHit[nhits + 1]; + hitsBuffer = new RaycastHit[hitsBuffer.Length * 2]; }; for (int i = 0; i < nhits; i++) {