Hello,
I am facing this odd issue where all the seekers decide to move to the edge of the grid graph simultaneously upon instantiation. what do you think could be the likely causes of the problem.
below is the initialization code for the AI (from the path-finding perspective):
- the path-finding is controlled from behavior tree nodes. here’s the code for the default wandering node & all the path-finding code from each entity that handles it.
//basic code for movement
public override void OnAwake()
{
// cache for quick lookup
aiPathAgent = gameObject.GetComponent();
aiPathAgent.targetVector = transform.position; // the target for the seeker
}
then when we need to set a new target we call this function…
protected override bool SetDestination(Vector3 target)
{
aiPathAgent.targetVector = target;
return true;
}
now for wandering code:
SetDestination(GetTarget());
Get Target is a function that returns a valid target, targets are are determined valid in this order:
- random point near the ai on the graph
- if the random point is not in a walkable area, check the same point in the opposite direction (-point basically)
- if both points are invalid, check if it’s possible to go to the spawn point.
- If not all of this, check if it’s possible to go to the center of the area you spawned in.
- if none of that works stand still. below is the code
protected Vector3 GetTarget()
{
var target = Vector3.zero;
var direction = transform.forward + Random.insideUnitSphere * wanderRate.Value;
if (TargetIsValid(transform.position, direction))
{
target = transform.position + direction.normalized * wanderDistance.Value;
if (entityWanderingDebug)
Debug.Log("Target point is valid....for: " + gameObject.name);
}
else if(TargetIsValid(transform.position, -direction))
{
target = transform.position + -direction.normalized * wanderDistance.Value;
if (entityWanderingDebug)
Debug.Log("Opposite Target point is valid....for: " + gameObject.name);
}
else if(TargetIsValid(transform.position, aiPathAgent.spawnPoint.spawnPosition))
{
target = transform.position + aiPathAgent.spawnPoint.spawnPosition.normalized * wanderDistance.Value;
if (entityWanderingDebug)
Debug.Log("Spawn point is valid....for: " + gameObject.name);
}
else if(aiPathAgent.spawnPoint is POISpawner &&
TargetIsValid(transform.position, poi.transform.position + Random.insideUnitSphere * wanderRate.Value))
{
target = transform.position + (poi.transform.position + Random.insideUnitSphere * wanderRate.Value).normalized * wanderDistance.Value;
if (entityWanderingDebug)
Debug.Log("Poi center is valid....for: " + gameObject.name);
}
else
{
target = transform.position;
if (entityWanderingDebug)
Debug.Log("No valid target, standing still....for: " + gameObject.name);
}
if (entityWanderingDebug)
Debug.Log("Target vector is: " + target);
return target;
}
lastly we validate the targets based on 2 conditions:
- a path is possible between both nodes
- the target is within the bounds of the AI’s spawn area. here’s the code for that.
protected override bool TargetIsValid(Vector3 currentPos, Vector3 targetPos)
{
var targetValid = false;
GraphNode currentPosNode = AstarPath.active.GetNearest(currentPos).node;
GraphNode targetPosNode = AstarPath.active.GetNearest(targetPos).node;
if (poi != null)
{
float poiDistanceThreshold = poiSizePercentage * poiSize;
targetValid = PathUtilities.IsPathPossible(currentPosNode, targetPosNode) && Vector3.Distance(targetPos, poi.transform.position)
< poiDistanceThreshold;
if (entityWanderingDebug)
{
Debug.Log("path possible: " + PathUtilities.IsPathPossible(currentPosNode, targetPosNode) + " For: "+gameObject.name);
Debug.Log("point less that poi threshold: " + (Vector3.Distance(targetPos, poi.transform.position)
< poiDistanceThreshold));
}
}
else
{
targetValid = PathUtilities.IsPathPossible(currentPosNode, targetPosNode);
if (entityWanderingDebug)
Debug.Log("path possible: " + PathUtilities.IsPathPossible(currentPosNode, targetPosNode));
}
return targetValid;
}