Hi All,
Long time lurker, first time poster
I’m getting some strange behavior on a game I’m mocking up while trying to use the UpdateGraphsNoBlock() function with a list of GraphNodes similarly to how it is being used in this other thread
The game is a 2d tile based game where each tile would correspond to a single node in the grid graph. In the picture below, the brown objects have already been placed while the red object is one that I’m trying to place. In order for an object’s placement to be valid, there must be a walkable path between each of the circled notches (or nodes) as well as a path to any of the blue tiles circled in the upper right hand corner. You can see that in this example, the placement is red for invalid because by placing the object there, it would block access for a number of the circled tiles, so it’s working correctly:
The problem I’m having is that if I were to move that object one tile to the right, I would expect that the placement would still be invalid because all of those tiles are still blocked, but now it’s showing that the placement is actually valid:
I plugged some Debug.Log statements into the UpdateGraphsNoBlock() function to see what I’m looking at there, and it looks like all of the correct points are getting added to the list of nodes to check, but it thinks that they’re still all in the same area.
If I were to then place the object down, however, all subsequent building will now return invalid, since one of the tiles that I would have expected to return invalid prior to placing the object is now correctly saying that it can’t reach one of the blue tiles.
I’m including code below, trimming off some of the extraneous stuff that I don’t think would be as relevant. Any thoughts or help would be much appreciated!
public void newtilehover(GameObject hovertile, bool manualoverride) {
//Don't do anything if it's the same tile being hovered over
if(hovertile == currenthover && manualoverride == false) {
return;
}
currenthover = hovertile;
OfficeTileAssignments.tile tile = tileAssignments.returntilebygameobject(hovertile);
List<OfficeTileAssignments.tile> requiredtiles = new List<OfficeTileAssignments.tile>();
requiredtiles = tileAssignments.returnalltilesforobject(objecttoplace, currentorientation, tile);
silhouetteinstance.transform.position = returncenterpos(currentorientation, tile);
updatesilhouettecollider(objecttoplace);
if(checkvalid(requiredtiles, objecttoplace) == true) {
setsilhouettesprite(objecttoplace, true);
validplacement = true;
currenthover = hovertile;
return;
}
//If the proposed object is still actually on the map, throw down the invalid silhouette
if(requiredtiles.Count == objecttoplace.width * objecttoplace.length) {
setsilhouettesprite(objecttoplace, false);
}
validplacement = false;
}
//
bool checkvalid(List<OfficeTileAssignments.tile> requiredtiles, placableobject proposedobject) {
//If the list of tiles provided is shorter than expected, this means you're trying to build off the edge of the map
if(requiredtiles.Count < proposedobject.width * proposedobject.length) {
return false;
}
//Check to make sure that none of the required tiles are already occupied
for(int i = 0; i < requiredtiles.Count; i++) {
if(requiredtiles[i].typeoftile != OfficeTileAssignments.typeoftile.floor) {
return false;
}
}
//Check that all "next to chair" tiles will still have a path to the breakroom/eachother
if(checkpathtobreakroom(requiredtiles, proposedobject, currentorientation, tileAssignments.returntilebygameobject(currenthover)) == false) {
return false;
}
return true;
}
//Manually set polygonpollider2d points to align with the required tiles to build the object
void updatesilhouettecollider(placableobject objecttoplace) {
if(objecttoplace.objecttype == typeofobject.salesdesk || objecttoplace.objecttype == typeofobject.tradingdesk) {
Vector2[] polypoints = new Vector2[8];
polypoints[0] = new Vector2(3,0);
polypoints[1] = new Vector2(1,0);
polypoints[2] = new Vector2(1,-2);
polypoints[3] = new Vector2(-1,-2);
polypoints[4] = new Vector2(-1,0);
polypoints[5] = new Vector2(-3,0);
polypoints[6] = new Vector2(-3,2);
polypoints[7] = new Vector2(3,2);
silhouettecollider.points = polypoints;
}
}
//This function compiles a list of all of the "next to desk" tiles and ensure that they will all
//still have a path to the breakroom if the new proposed object is placed
bool checkpathtobreakroom(List<OfficeTileAssignments.tile> tilestouse, placableobject proposedobject, objectorientation orientation, OfficeTileAssignments.tile hovertile) {
List<GraphNode> allnodes = new List<GraphNode>();
OfficeTileAssignments.tile breakroomtile = tileAssignments.returnanybreakroomtile();
var breakroomnode = AstarPath.active.GetNearest(breakroomtile.tilegameobject.transform.position).node;
allnodes.Add(breakroomnode);
//Cycle through all existing desks, and adds their "next to chair" nodes to the list of nodes to check
Dictionary<DeskAssignments.desk, character> alldesks = deskAssignments.returnalldesks();
foreach(KeyValuePair<DeskAssignments.desk, character> desk in alldesks) {
OfficeTileAssignments.tile desknode_1 = null;
OfficeTileAssignments.tile desknode_2 = null;
if(desk.Key.orientation == objectorientation.left) {
desknode_1 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x, desk.Key.chairlocation.y + 1});
desknode_2 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x, desk.Key.chairlocation.y - 1});
}
else if(desk.Key.orientation == objectorientation.up) {
desknode_1 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x + 1, desk.Key.chairlocation.y});
desknode_2 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x - 1, desk.Key.chairlocation.y});
}
else if(desk.Key.orientation == objectorientation.down) {
desknode_1 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x + 1, desk.Key.chairlocation.y});
desknode_2 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x - 1, desk.Key.chairlocation.y});
}
else if(desk.Key.orientation == objectorientation.right) {
desknode_1 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x, desk.Key.chairlocation.y + 1});
desknode_2 = tileAssignments.returntilebycoordinates(new int[]{desk.Key.chairlocation.x, desk.Key.chairlocation.y - 1});
}
var startnode_1 = AstarPath.active.GetNearest(desknode_1.tilegameobject.transform.position).node;
var startnode_2 = AstarPath.active.GetNearest(desknode_2.tilegameobject.transform.position).node;
allnodes.Add(startnode_1);
allnodes.Add(startnode_2);
}
//If the new object is an additional desk, add the two new "next to chair" nodes to the list of nodes to check
if(proposedobject.objecttype == typeofobject.desk) {
if(orientation == objectorientation.up) {
int[] coordinates = new int[2];
coordinates[0] = hovertile.x + 1;
coordinates[1] = hovertile.y - 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
coordinates[0] = hovertile.x - 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
}
else if(orientation == objectorientation.down) {
int[] coordinates = new int[2];
coordinates[0] = hovertile.x + 1;
coordinates[1] = hovertile.y + 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
coordinates[0] = hovertile.x - 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
}
else if(orientation == objectorientation.left) {
int[] coordinates = new int[2];
coordinates[0] = hovertile.x + 1;
coordinates[1] = hovertile.y + 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
coordinates[1] = hovertile.y - 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
}
else if(orientation == objectorientation.right) {
int[] coordinates = new int[2];
coordinates[0] = hovertile.x - 1;
coordinates[1] = hovertile.y + 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
coordinates[1] = hovertile.y - 1;
allnodes.Add(AstarPath.active.GetNearest(tileAssignments.returntilebycoordinates(coordinates).tilegameobject.transform.position).node);
}
}
//Manually creating new bounds in case I decide to use some really funky shapes in the future
float min_x = silhouettecollider.points.Min(point => point.x);
float max_x = silhouettecollider.points.Max(point => point.x);
float x_extent = 0;
if(min_x >= max_x) {
x_extent = min_x;
}
else {
x_extent = max_x;
}
float min_y = silhouettecollider.points.Min(point => point.y);
float max_y = silhouettecollider.points.Max(point => point.y);
float y_extent = 0;
if(min_y >= max_y) {
y_extent = min_y;
}
else {
y_extent = max_y;
}
Vector3 extents = new Vector3();
extents.x = x_extent;
extents.y = y_extent;
extents.z = 0;
Bounds updatearea = new Bounds();
updatearea.center = silhouettecollider.transform.position;
updatearea.extents = extents;
Debug.Log("Bound for the update area are " + updatearea);
//Creating new object area with the new bounds and checking if all nodes as still valid
var guo = new GraphUpdateObject(updatearea);
return GraphUpdateUtilities.UpdateGraphsNoBlock(guo, allnodes, alwaysRevert: true);
}