From c21ba35ba03f9fd68feb2bcf072250678aa65058 Mon Sep 17 00:00:00 2001 From: HazDS Date: Wed, 18 Feb 2026 21:32:57 +0000 Subject: [PATCH] Project destinations to NavMesh height Sample NavMesh height for destination markers in LocationDialogueSpec and WalkToSpec so destination markers use the navmesh Y coordinate when creating NPC markers. This makes distance checks and walk completion logic consistent with where NPCs actually walk (fixes WalkResult.Partial / unreachable ReachedDestination and FaceDirection not being called). --- .../ActionSpecs/LocationDialogueSpec.cs | 12 +++++++++++- .../Schedule/ActionSpecs/WalkToSpec.cs | 19 ++++++++++++++++--- S1API/S1API.csproj | 4 ++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/S1API/Entities/Schedule/ActionSpecs/LocationDialogueSpec.cs b/S1API/Entities/Schedule/ActionSpecs/LocationDialogueSpec.cs index c1120fc7..b37190ef 100644 --- a/S1API/Entities/Schedule/ActionSpecs/LocationDialogueSpec.cs +++ b/S1API/Entities/Schedule/ActionSpecs/LocationDialogueSpec.cs @@ -15,6 +15,7 @@ using S1ObjectScripts = ScheduleOne.ObjectScripts; #endif using UnityEngine; +using UnityEngine.AI; using S1API.Map; using S1API.Vehicles; @@ -112,11 +113,20 @@ void IScheduleActionSpec.ApplyTo(NPCSchedule schedule) if (action == null) return; + // Project destination to navmesh height so the game's 3D distance checks + // use a position consistent with where the NPC actually walks. + Vector3 markerPosition = Destination; + NavMeshHit navHit; + if (NavMesh.SamplePosition(Destination, out navHit, 5f, NavMesh.AllAreas)) + { + markerPosition = new Vector3(Destination.x, navHit.position.y, Destination.z); + } + // Create destination marker in NPC's dedicated container var destinationTransform = NPCDestinationContainer.CreateDestinationMarker( schedule.NPC.gameObject.name, "Marker", - Destination, + markerPosition, Forward); if (destinationTransform != null) diff --git a/S1API/Entities/Schedule/ActionSpecs/WalkToSpec.cs b/S1API/Entities/Schedule/ActionSpecs/WalkToSpec.cs index 5f22150f..4e46b308 100644 --- a/S1API/Entities/Schedule/ActionSpecs/WalkToSpec.cs +++ b/S1API/Entities/Schedule/ActionSpecs/WalkToSpec.cs @@ -15,6 +15,7 @@ using S1ObjectScripts = ScheduleOne.ObjectScripts; #endif using UnityEngine; +using UnityEngine.AI; using S1API.Map; using S1API.Vehicles; @@ -111,11 +112,23 @@ void IScheduleActionSpec.ApplyTo(NPCSchedule schedule) } } + // Project destination to navmesh height so the game's 3D distance checks + // (WalkResult.Success threshold and IsAtDestination) use a position consistent + // with where the NPC actually walks. Without this, a Y-coordinate mismatch > 1 unit + // causes WalkResult.Partial instead of Success, and ReachedDestination() never fires, + // so FaceDirection is never called. + Vector3 markerPosition = Destination; + NavMeshHit navHit; + if (NavMesh.SamplePosition(Destination, out navHit, 5f, NavMesh.AllAreas)) + { + markerPosition = new Vector3(Destination.x, navHit.position.y, Destination.z); + } + // Create destination marker in NPC's dedicated container var destinationTransform = NPCDestinationContainer.CreateDestinationMarker( - schedule.NPC.gameObject.name, - "Destination", - Destination, + schedule.NPC.gameObject.name, + "Destination", + markerPosition, forwardDirection); if (destinationTransform != null) diff --git a/S1API/S1API.csproj b/S1API/S1API.csproj index 5227985a..52bb3eb3 100644 --- a/S1API/S1API.csproj +++ b/S1API/S1API.csproj @@ -65,6 +65,7 @@ + @@ -111,6 +112,9 @@ $(MonoAssembliesPath)/UnityEngine.PhysicsModule.dll + + $(MonoAssembliesPath)/UnityEngine.AIModule.dll + $(MonoAssembliesPath)/Unity.TextMeshPro.dll