StackOverflowException: The requested operation caused a stack overflow

Hi,

I sometimes get a StackOverflowException for some reason. I have no idea what the pattern is. The only special thing is that I’m using a custom ITraversalProvider (code below).

public class CustomTraversable : PlayerActorTraversable
{
    public readonly float Bias = 0f;
    public override bool ModifiesDefault => AvoidanceSdVolume.TryGetDistanceToVolumes(Vector3.zero, OwnerDescriptor, out _);

    /// <summary>
    /// Assigns weights to nodes based on the distance to obstacles
    /// </summary>
    /// <param name="bias">The higher the bias, the more it is trying avoiding the obstacles. Keep in 0-1 range</param>
    public CustomTraversable(float bias, PlayerActorDescriptor ownerDescriptor)
        : base(ownerDescriptor)
    {
        Bias = Mathf.Clamp01(bias);
    }

    public override bool CanTraverse(Path path, GraphNode node)
    {
        bool canTraverse = DefaultITraversalProvider.CanTraverse(path, node);
        if (AvoidanceSdVolume.TryGetDistanceToVolumes((Vector3)node.position, OwnerDescriptor, out float distToSdf))
            canTraverse &= distToSdf >= .5f;
        return canTraverse;
    }

    public override uint GetTraversalCost(Path path, GraphNode node)
    {
        float cost = DefaultITraversalProvider.GetTraversalCost(path, node);
        if (AvoidanceSdVolume.TryGetDistanceToVolumes((Vector3)node.position, OwnerDescriptor, out float distToSdf))
            cost += Bias * 10e4f * Mathf.Pow(1f / Mathf.Max(distToSdf, 0.01f), 5f);
        return (uint)cost;
    }
}

crash log

StackOverflowException: The requested operation caused a stack overflow.
UnityEngine.Mathf.Abs (System.Single f) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
.sdPrism (UnityEngine.Vector3 p, System.Single angle) (.cs:260)
.SignedDistanceTo... (UnityEngine.Vector3 poinInLocalSpace, System.Single innerRadius, System.Single outerRadius, System.Single verticalAngle, System.Single horizontalAngle) (.cs:226)
.TryGetDistanceToVolume (UnityEngine.Vector3 point, System.Single& distance) (.cs:42)
AvoidanceSdVolume.TryGetDistanceToVolumes (UnityEngine.Vector3 point, System.Single& distance) (.cs:76)
CustomTraversable.Pathfinding.ITraversalProvider.GetTraversalCost (Pathfinding.Path path, Pathfinding.GraphNode node) (...CustomTraversable.cs:28)
Pathfinding.Path.GetTraversalCost (Pathfinding.GraphNode node) (at Assets/AstarPathfindingProject/Core/Path.cs:388)
Pathfinding.PathNode.UpdateG (Pathfinding.Path path) (at Assets/AstarPathfindingProject/Core/PathHandler.cs:106)
Pathfinding.TriangleMeshNode.UpdateRecursiveG (Pathfinding.Path path, Pathfinding.PathNode pathNode, Pathfinding.PathHandler handler) (at Assets/AstarPathfindingProject/Generators/NodeClasses/TriangleMeshNode.cs:219)
Pathfinding.TriangleMeshNode.UpdateRecursiveG (Pathfinding.Path path, Pathfinding.PathNode pathNode, Pathfinding.PathHandler handler) (at Assets/AstarPathfindingProject/Generators/NodeClasses/TriangleMeshNode.cs:228)
Pathfinding.TriangleMeshNode.UpdateRecursiveG (Pathfinding.Path path, Pathfinding.PathNode pathNode, Pathfinding.PathHandler handler) (at Assets/AstarPathfindingProject/Generators/NodeClasses/TriangleMeshNode.cs:228)
[...alot of these...]`Preformatted text`

Hi

Are you sure your GetTraversalCost method returns the exact same cost every time it is invoked from a path? Keep in mind that paths may be calculated on a separate thread.

Hi @aron_granberg , thanks for the fast reply. The obstacle is dynamic and updates the data structure every frame, so it is not guaranteed that the distance from A to B is the same at different times. I was thinking of locking the data structure update if there is any path being calculated, but can’t find any property that says if AstarPath is busy calculating any path. I tried IsAnyWorkItemInProgress , but that’s only for the graph, not the paths. I can of course create my own counter by tracking the paths as I request them. Do you have any suggestions?

Hi

In general, pathfinding can happen at any time except during graph updates.
You could update your data structure only during times when paths are guaranteed not to be calculated. You can do this by registering a callback to AstarPath.AddWorkItem.

AstarPath.AddWorkItem(() => {
    // Update your datastructure here
});

Got it, thanks! Works like a charm now.

1 Like