I’ve been implementing an A* algorithm, and have been trying to add basic collision detection, and am failing very badly and just getting frustrated. Basically, the unit’s update class checks if the unit has any vectors in the movement vector list. If so, it goes through a number of steps to decide what to do.
First, it rotates to face the target vector, then it creates a forward vector, which is meant to be based off the gameObject’s position and takes rotation into account. So this can be used to check if there is anything in the node closest to that vector which would obstruct movement.
// unit MUST rotate before moving (otherwise forward node checks ruined)
transform.LookAt(listMovePos[0]);
// normalise the X and Z axis (only Y axis must change)
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
// forward checks node ahead of current node
Vector3 forward = transform.position;
forward += transform.forward * 0.6f;
Node forwardNode = Map.mapNodes[(int)forward.x, (int)forward.z];
That works in straight lines, but if the unit is trying to move diagonally past a stationary unit in an adjacent node, it sometimes freaks out and thinks that the occupied node is the one it’s trying to enter… which it is not, since the other unit is sitting stationary for the duration of the unit moving along its path of vectors.
I’m just fed up and don’t know what to do. Any suggestions greatly appreciated! Is there a specific piece of code I need to use to take any direction into account, instead of the above? Is there something else likely logically wrong, like the distance being too short for diagonals (in which case any suggestions)? Or is it possibly something else entirely?
In the above you can see a visualisation of the pathfinding. Blue tiles are open list, green are closed list. Cyan is start, red is end. Yellow is created upon the node the unit thinks is obstructed. As you can see, that node is indeed occupied by a sphere; but the unit’s path successfully navigates around it diagonally, and yet gets confused and detects that node incorrectly.
The sphere is moving along the green tiles from cyan to red, and attempts to move around the other sphere by moving outwards and then inwards diagonally; moving outwards is fine regardless of the direction of travel, but moving inwards then always glitches the system and detects a false positive obstruction.
EDIT:
I have been following Glurth’s advice, and investigating further, and there must be something simple wrong with the vector, as upon using more visualisation aides, it appears that the vector3 it is checking is ALWAYS off consistently.

In this photo the magenta tiles show the vector3s the movement is checking. They should be aligned almost exactly with the green path tiles, but they are not; they are completely off (in this case by about +0.8f, I am really confused now) So I’m just going to dump the whole code here and see if anyone can spot what is causing the unit to be checking a vector3 which is clearly not straight ahead of where it is looking? Any other improvements appreciated too, but this particular issue is crippling.
void Update ()
{
// refresh node this unit is occupying
node = Map.mapNodes[(int) transform.position.x, (int) transform.position.z];
if (listMovePos.Count > 0) // unit is moving
{
node.occupiedByMover = true;
// unit MUST rotate before moving (otherwise forward node checks buggered)
transform.LookAt(listMovePos[0]);
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0); // set X and Z axis (only Y axis must change)
// forward checks node ahead of current node
Vector3 forward = transform.position;
Vector3 normal = transform.position;
normal.Normalize();
forward += normal;
Node forwardNode = Map.mapNodes[(int)forward.x, (int)forward.z];
Map.Instance.CreateThing(new Vector3(forward.x, forward.y + 0.7f, forward.z), forwardNode, Color.magenta); // test
// refresh old node when this unit moves into new node
if (node != lastNode)
{
lastNode.occupiedByMover = false;
lastNode.occupied = false;
}
// then update old node
lastNode = node;
// assuming unit size 1, remove first index (that has been reached)
if (Vector3.Distance(transform.position, listMovePos[0]) < 0.1)
{
listMovePos.RemoveAt(0);
node.occupiedByMover = false;
node.occupied = true;
}
else // movement logic...
{
// this unit is about to move into a new node
if (forwardNode != null && forwardNode != node)
{
// this unit must wait if another unit is moving in forward node
if (forwardNode.occupiedByMover)
{
Debug.Log(" //NODE OCCUPIED BY MOVER");
Map.Instance.CreateThing(new Vector3(forwardNode.getVectorX(), forwardNode.getVectorY() + 0.7f, forwardNode.getVectorZ()), forwardNode, Color.yellow); // test
}
// this unit must repath around forward node occupied by a stationary unit
else if (forwardNode.occupied)
{
//move = false;
Debug.Log(" //NODE OCCUPIED");
Map.Instance.CreateThing(new Vector3(forwardNode.getVectorX(), forwardNode.getVectorY() + 0.7f, forwardNode.getVectorZ()), forwardNode, Color.yellow); // test
}
else // move normally
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
else // move normally
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
}
else // unit is stationary
{
node.occupied = true;
}
}