I want to make AstarPath.active.GetNearest( transform.position, NNConstraint.None )
to use
ABPath path = ABPath.Construct( from, to ); if( traversalProvider != null ) { path.traversalProvider = traversalProvider; } AstarPath.StartPath( path );
as I am trying to use the grid/hex graph to find the closest available node.
I tried something of the sort but doesn’t work:
In BlockManager:
public bool IsNodeBlocked( GraphNode node )
{
return m_BlockedDictionary.ContainsKey( node ) && m_BlockedDictionary[ node ].Count > 0;
}
public class BlockedConstraint : NNConstraint
{
public override bool Suitable( GraphNode node )
{
return base.Suitable( node ) && !BlockManager.Instance.IsNodeBlocked( node );
}
/// <summary>Returns a constraint which does not filter the results</summary>
public static NNConstraint Blocked
{
get
{
return new BlockedConstraint();
}
}
}
GraphNode node = AstarPath.active.GetNearest( transform.position, BlockedConstraint.Blocked ).node;
Hi
Your code should work. That’s exactly how I’d implement it. Assuming your blocked dictionary is filled out correctly.
1 Like
hmm I instantiate all characters in runtime at the same time, could there be a race condition between the pathfinding searching and the check?
The path search doesn’t modify the traversal provider, so I don’t think so.
My code does right after the search this way:
public void Init( List<GridElement> friends = null )
{
GraphNode node = AstarPath.active.GetNearest( transform.position, BlockedConstraint.Blocked ).node;
transform.position = ( Vector3 )node.position;
// Set the traversal provider to block all nodes that are blocked by a SingleNodeBlocker
// except the SingleNodeBlocker owned by this AI (we don't want to be blocked by ourself)
m_TraversalProvider = new BlockManager.TraversalProvider( BlockManager.BlockMode.AllExceptSelector, friends );
Block( node );
}
I guess GetNearest is instant, not multithreaded so it shouldn’t have a race condition
I tried this and it’s positioning some of them ontop of eachother.
if( Input.GetKeyDown( KeyCode.Alpha1 ) )
{
for( int i = 0; i < 100; i++ )
{
GridElement element = GameObject.CreatePrimitive( PrimitiveType.Cube ).GetOrAddComponent<GridElement>();
element.GetComponent<Renderer>().material.color = Color.red;
element.transform.position = new Vector3().Random( -15, 15 );
element.transform.position = new Vector3( element.transform.position.x, 0, element.transform.position.z );
element.Init();
}
}
EDIT1: OK I think this is the cause:
public void InternalBlock( GraphNode node, GridElement blocker )
{
AstarPath.active.AddWorkItem( new AstarWorkItem( () =>
{
List<GridElement> blockersInNode;
if( !m_BlockedDictionary.TryGetValue( node, out blockersInNode ) )
{
blockersInNode = m_BlockedDictionary[ node ] = ListPool<GridElement>.Claim();
}
blockersInNode.Add( blocker );
} ) );
}
EDIT2: I tried not to flood the channel
Ah. Yeah that will be it.
You can force the work item to complete immediately by using AstarPath.active.FlushWorkItems()
.
1 Like
I removed the threading process, isn’t it just a dictionary process? I haven’t read what ListPool.Claim(); does which was my only worry removing this
What do you mean by this?
public void InternalBlock( GraphNode node, GridElement blocker )
{
//AstarPath.active.AddWorkItem( new AstarWorkItem( () =>
{
List<GridElement> blockersInNode;
if( !m_BlockedDictionary.TryGetValue( node, out blockersInNode ) )
{
blockersInNode = m_BlockedDictionary[ node ] = ListPool<GridElement>.Claim();
}
blockersInNode.Add( blocker );
} //) );
}
sorry my english drifted as I was writting this sentence I meant that I removed the threading process as I thought it’s ok to not have this multithreaded as removing an element from a dictionary isnt that slow, is it?