- Home /
Hexagon A* Pathfinding - limiting path length
Hi all.
I've been working further with Aron Granberg's A* pathfinding, using List Graphs to create paths between nodes on a hexagon grid, for a turn-based game. What I am attempting to do now though, is to limit the number of nodes to be traversed by a particular unit.
At the moment I have working pathfinding, and a few scripts that are supposed to limit the path length. There are two game objects, a blue unit and a red unit, each with the same script for 'movement range' (but red having 2 range and blue having 6 range). When either unit is selected, it enables me to set a path, and the unit stops at its maximum range, even if the path itself is longer. The issue arises when I choose the red unit and set a path longer than it's maximum movement range. It moves 2 hexes and stops, which is correct. But then if I then select the blue unit, the red unit decides "hey now I have movement of 6!" and proceeds to move the other 4 units to end up having moved 6 hexes from it's original hex.
I think that the solution involves creating instances of the units, so that each time the pathfinding script is called it creates it's own little world, and can't be interacted with by a second pathfinding script call... but I don't know how to do that, or if it's even the right thing to do.
Here are my scripts so far.
First, the unit select and start-the-path script (which also changes the material at the very end, for 1 second):
public class aaTouchRaycaster : MonoBehaviour {
public Ray ray;
public RaycastHit hit;
public Vector3 targetPosition;
public AstarAI aStarAIScript;
public aaManager aaManagerScript;
public aaCountdowns aaCountdownsScript;
void Update () {
int i = 0;
while (i < Input.touchCount) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
//if selectedUnit = null, do nothing
if (Physics.Raycast(ray, out hit, 100) && hit.collider.gameObject.tag == "HexTile" && aaManagerScript.selectedUnit == null)
Debug.Log("there is no unit selected!");
//if selectedUnit = something, send it on it's path to the targetPosition node
if (Physics.Raycast(ray, out hit, 100) && hit.collider.gameObject.tag == "HexTile" && aaManagerScript.selectedUnit != null) {
Node node = AstarPath.active.GetNearest (aaManagerScript.selectedUnit.transform.position);
targetPosition = AstarPath.active.GetNearest (hit.point);
if (node.walkable)
aaManagerScript.selectedUnit.GetComponent<AstarAI>().MoveOnThePath();
}
//selects a unit
//ie: sets the game object hit by the Raycast as the selected 'unit' in the aaManagerScript.selectedUnit GameObject variable
if (Physics.Raycast(ray, out hit, 100) && hit.collider.gameObject.layer == 9) {
aaManagerScript.selectedUnit = hit.collider.gameObject;
aaManagerScript.origMaterial = aaManagerScript.selectedUnit.renderer.material;
aaManagerScript.selectedUnit.renderer.material = aaManagerScript.newMaterial;
aaCountdownsScript.matCountdown = true;
aaCountdownsScript.matResetTimer = 1.0f;
}
}
++i;
}
}
}
And secondly, the A* script, which I have added in my attempt at restricting movement range:
public class AstarAI : MonoBehaviour {
public aaTouchRaycaster rayScript;
public aaManager aaManagerScript;
public GameObject targetNode;
private Seeker seeker;
private CharacterController controller;
//the calculated path
public Path path;
//the AI's speed per second
public float speed = 100;
//the max distance from the AI to a waypoint for it to continue to the next waypoint
public float nextWaypointDistance = 1;
//the waypoint we are currently moving towards
private int currentWaypoint = 0;
public bool nodeIsClose = false;
public float countdownResetValue = 2.0f;
public float countdown = 2.0f;
public void Start () {
controller = GetComponent<CharacterController>();
}
public void MyCompleteFunction (Path p) {
if (!p.error) {
path = p;
//reset the waypoint counter
currentWaypoint = 0;
}
}
public void Update () {
if(path == null)
return;
if(currentWaypoint >= path.vectorPath.Length)
return;
Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position.normalized;
dir *= speed * Time.deltaTime;
controller.SimpleMove(dir);
if(Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance){
nodeIsClose = true;
}else{
nodeIsClose = false;
return;
}
if(nodeIsClose)
countdown -= Time.deltaTime;
if(nodeIsClose && countdown <= 0.0f){
if(currentWaypoint <= aaManagerScript.selectedUnit.GetComponent<UnitStats>().uMoveRange - 1){
currentWaypoint++;
countdown = countdownResetValue;
}
if(currentWaypoint == aaManagerScript.selectedUnit.GetComponent<UnitStats>().uMoveRange - 1)
Debug.Log("final node set");
}
}
}
The reason for the -1 in the uMoveRange is that the first waypoint is registered as 0 (zero), the second waypoint as 1, etc, as opposed to the unit's movement range starting from 1, not 0.
TLDR; I don't know how to get a working movement range using pathfinding with multiple units.
Thanks in advance to whomever can help me out with this predicament. :)
Your answer
Follow this Question
Related Questions
How can I get my pathfinding algorithm to know that it cant go through certain sides of tiles 1 Answer
3D Grid Based Movement (X-Com 2012 etc) – How to implement vertical movement? 0 Answers
Selecting custom game objects in Scene view window. 1 Answer