A* version: [5.2.5] (purchased version of A* Pathfinding Project Pro)
Unity version: [6000.0.31f1]
Burst version: [1.8.18]
Collections: [2.5.1]
Hello, and happy holidays! I’m still loving this library btw, but have a small issue I wonder if you could help me with?
I am encountering a problem with Linecast, which incorrectly returns true on some occasions, and false on others even though it’s the same scene, same graph, same start/end positions. I use one graph (a Recast graph) and its mostly flat, no overlaps or additional “floors”.
The function I call is:
recastGraph.Linecast(vec1, vec2);
The return true occus on line 1559 of NavmeshBase. It fails because the endNode is not equal to node.
if (endNode == node …
I wonder, is this comparison valid? Why should the end node be the same as the start/origin node?
I do not supply a GraphNode hint, and subsequently node is derived from the origin:
if (node == null) {
var nn = graph.GetNearest(origin, NNConstraintNoneXZ);
node = nn.node as TriangleMeshNode;
So if my origin and end vectors shared the same node this would work, otherwise wouldn’t this always fail?
Sure, I have the steps and a short script below to recreate the issue.
Linecast fails in NavmeshBase when the point lies exactly on a shared edge i.e. when sideNodeExit is Colinear.
Steps to recreate:
Create a New Scene
Add this new script “LinecastTests.cs” to the project:
using Pathfinding;
using System.Collections;
using UnityEngine;
public class LinecastTests : MonoBehaviour
{
public GameObject testTarget;
private RecastGraph recastGraph;
private bool isTesting = false;
private bool hasInitialised = false;
private float testInterval = 1f;
void Start()
{
recastGraph = AstarPath.active.data.recastGraph;
}
void Update()
{
if (!isTesting)
StartCoroutine(StartTest());
}
private IEnumerator StartTest()
{
isTesting = true;
yield return new WaitForSeconds(testInterval);
Vector3 start = transform.position;
Vector3 end = testTarget.transform.position;
if (!hasInitialised)
{
hasInitialised = true;
// See debug Lines before moving the target
DrawPath(start, end);
yield return new WaitForSeconds(testInterval);
// Now ensure the target node is at a Colinear position
NNInfo closetNode = recastGraph.GetNearest(end, null);
TriangleMeshNode triNode = closetNode.node as TriangleMeshNode;
Int3 v0, v1, v2;
triNode.GetVertices(out v0, out v1, out v2);
// Use the first vertex of the triangle
end = (Vector3)v0;
testTarget.transform.position = end;
}
DrawPath(start, end);
isTesting = false;
}
private void DrawPath(Vector3 start, Vector3 end)
{
bool clearPath = !recastGraph.Linecast(start, end);
Debug.DrawLine(start, end, clearPath ? Color.green : Color.red, testInterval);
}
}
Add a Plane 3D Object at {0,0,0}. Give it a scale of {10,1,10}
Create a GameObject called AStar at {0,0,0}
Add the AStarPath component to the AStar GameObject.
Add a Recast graph and leave at default settings (optionally change character radius to 1 to remove warning)
Hit Scan graph to make sure you are seeing some triangles
Add a Sphere 3D Object called testTarget at {30,1,30}
Remove the Collider component
Add a Sphere 3D Object called testStart at {-30,1,-30}
Remove the Collider component
Add the LinecastTests script to the testStart object
Set the Test Target script property to be the testTarget object
Make sure the testTarget and testStart objects are in different triangles.
Play the scene
The debug line should be green, showing Linecast is correctly saying no obstacles between the spheres.
After a second, the testTarget sphere should move on to a node edge.
The line should now be red, showing Linecast is incorrectly saying it has no line of sight between the spheres.
While the scene is still playing, select the testTarget sphere, and using the translate tool axis arrows, move it around.
If you slide the sphere down on a line, the line remains red.
It might not seem like a serious issue, because the chances of putting a path point exactly on a line seem slim, however if you are using a Funnel Modifier like me, your vectorPath will consist almost entirely of triangle corners and edges. Subsequently, using a MonoModifier to tweak the paths becomes problematic.
Luckily there is a small hack we can use in the interim - just apply a tiny nudge:
// Tiny nudge to get off lines
Vector3 nudge = dirNormalised * 0.01f;
start = start + nudge;
end = end - nudge;
Outstanding recreation steps, thank you! Yeah I got the same behavior on my end as well. I’ll tag @aron_granberg in this so he’s aware of this bug. Good find!!
And thanks for sharing your interim fix with the community as well
I’ve managed to reproduce this and I’ve implemented a fix.
It was only a one-line fix! Though it took some time to figure out which line :p. My original fix was like 20 lines of complex math.
The fix will be included in the next update.
[EDIT] Ok, had to make a more elaborate fix. But should work well now.
Hi @aron_granberg , I have imported the new package 5.3.0, and this does seem to have improved the LineCast issue.
In some situations it now works, however, I still get similar results using my steps above.
Using the same recreation steps I still see a negative result:
Interestingly, if I swap the positions of testStart and testTarget while running, it works correctly, even though one of the points is on the same corner, but I assume its the target location which is important here.
However, if I move testStart (while still playing) out of the lower left quadrant (from South East) to any other quadrant (North, East, West), it works correctly:
In addition, when I move off of the complicated corner, but still on a shared edge/line, it now works correctly (where it didn’t in the previous version):
Just another note about 5.3.0, which is a more serious issue for me, I am now seeing some significant performance deterioration issues with Navmesh Cut, that I wasn’t seeing previously.
I am doing some more testing, but have a couple of questions before I create a new post relating to it.
I have noticed in the package manager that the dependencies for AStar are a fair bit older that what I am using. Should I be sticking with the versions defined by your asset?
Is it possible to downgrade/rollback AStar to a previous version? If so, do you know how to do that - where can I download it from?
The performance shouldn’t have changed significantly between 5.2.5 and 5.3.0. Are you sure this is the case? And if so, do you think you could post some profiling screenshots?
Nah. Those are just the oldest supported versions. Use newer versions if you can.
Unity makes this hard, for unclear reasons. I would recommend installing it via a custom repository instead. See A* Pathfinding Project
Then you can switch between versions via the unity package manager.
Yes, unfortunately it is very significant for me, and I can recreate it easily. I have done some comparisons and profiling - I will post a new topic on this forum.
Thanks for the tips on the custom repository, this works well.