private IPathNode Jump(IPathNode current, VectorXZ direction) { var next = current.GetNeighbour(direction.x, direction.z); if (next == null || !next.IsWalkableFromWithClearance(current, _unitProps)) { return(null); } if (next == this.goal) { return(next); } if (HasForcedNeighbour(next, direction)) { return(next); } if (direction.x != 0 && direction.z != 0) { if (Jump(next, new VectorXZ(direction.x, 0)) != null || Jump(next, new VectorXZ(0, direction.z)) != null) { return(next); } //If both or either neighbours (depending on cut corner setting) in a diagonal move are blocked, the diagonal neighbour is not reachable since the passage is blocked var n1 = next.GetNeighbour(direction.x, 0); var n2 = next.GetNeighbour(0, direction.z); bool jumpOn = _cutCorners ? ((n1 != null && n1.IsWalkableFromWithClearance(current, _unitProps)) || (n2 != null && n2.IsWalkableFromWithClearance(current, _unitProps))) : ((n1 != null && n1.IsWalkableFromWithClearance(current, _unitProps)) && (n2 != null && n2.IsWalkableFromWithClearance(current, _unitProps))); if (jumpOn) { return(Jump(next, direction)); } } else { return(Jump(next, direction)); } return(null); }
Cell IGridCell.GetNeighbour(VectorXZ offset) { return(null); }
/// <summary> /// Gets the neighbour at the specified matrix offset. /// </summary> /// <param name="offset">The offset.</param> /// <returns> /// The neighbour cell or null /// </returns> public Cell GetNeighbour(VectorXZ offset) { return(GetNeighbour(offset.x, offset.z)); }
private bool DrawAccessibility(IGrid grid, Cell start, Cell end, Color lineColor) { var matrix = grid.cellMatrix; var cellSize = grid.cellSize; VectorXZ[] directions = new[] { new VectorXZ(-1, 0), new VectorXZ(-1, 1), new VectorXZ(0, 1), new VectorXZ(1, 1) }; var heightAdj = new Vector3(0.0f, 0.05f, 0.0f); for (int x = start.matrixPosX; x <= end.matrixPosX; x++) { for (int z = start.matrixPosZ; z <= end.matrixPosZ; z++) { var c = matrix[x, z]; if (c == null) { return(false); } if (!c.isWalkable(this.modelAttributes)) { Gizmos.color = this.obstacleColor; Gizmos.DrawCube(c.position, new Vector3(cellSize, 0.05f, cellSize)); continue; } var curPos = new VectorXZ(x, z); for (int i = 0; i < 4; i++) { var checkPos = curPos + directions[i]; var other = matrix[checkPos.x, checkPos.z]; if (other != null) { if (!other.isWalkable(this.modelAttributes)) { continue; } //Determine top and bottom, with bottom winning over top if equal so to speak, due to cross height. var topPos = c; var bottomPos = other; if (topPos.position.y <= bottomPos.position.y) { topPos = bottomPos; bottomPos = c; } var topDown = bottomPos.isWalkableFrom(topPos, _modelProps); var downTop = topPos.isWalkableFrom(bottomPos, _modelProps); if (topDown && downTop) { Gizmos.color = lineColor; } else if (topDown) { Gizmos.color = this.descentOnlyColor; } else if (downTop) { Gizmos.color = this.ascentOnlyColor; } else { continue; } Gizmos.DrawLine(c.position + heightAdj, other.position + heightAdj); } } /* end for each selected neighbour */ } } return(true); }
private void PruneNeighbours(IPathNode current, VectorXZ direction) { if (direction.x != 0) { if (direction.z != 0) { //Natural neighbours var nTop = current.TryGetWalkableNeighbour(0, direction.z, _unitProps, _neighbours); var nRight = current.TryGetWalkableNeighbour(direction.x, 0, _unitProps, _neighbours); if (_cutCorners) { if (nTop || nRight) { current.TryGetWalkableNeighbour(direction.x, direction.z, _unitProps, _neighbours); } //Forced neighbours? The left/down is as seen from a normal view of the grid, i.e. not seen from the direction of movement (well direction left corner diagonal) var nLeft = current.GetNeighbour(-direction.x, 0); if (nLeft != null && !nLeft.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(-direction.x, direction.z, _unitProps, _neighbours); } var nDown = current.GetNeighbour(0, -direction.z); if (nDown != null && !nDown.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(direction.x, -direction.z, _unitProps, _neighbours); } } else { if (nTop && nRight) { current.TryGetWalkableNeighbour(direction.x, direction.z, _unitProps, _neighbours); } } } else { //Natural neighbour current.TryGetWalkableNeighbour(direction.x, 0, _unitProps, _neighbours); //Forced neighbours? if (_cutCorners) { var nUp = current.GetNeighbour(0, 1); if (nUp != null && !nUp.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(direction.x, 1, _unitProps, _neighbours); } var nDown = current.GetNeighbour(0, -1); if (nDown != null && !nDown.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(direction.x, -1, _unitProps, _neighbours); } } else { var nUpBack = current.GetNeighbour(-direction.x, 1); if (nUpBack != null && !nUpBack.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(0, 1, _unitProps, _neighbours); current.TryGetWalkableNeighbour(direction.x, 1, _unitProps, _neighbours); } var nDownBack = current.GetNeighbour(-direction.x, -1); if (nDownBack != null && !nDownBack.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(0, -1, _unitProps, _neighbours); current.TryGetWalkableNeighbour(direction.x, -1, _unitProps, _neighbours); } } } } else { //Portals return Vector3.zero as the direction, and for those we need to start over on the new grid. if (direction.z == 0) { current.GetWalkableNeighbours(_neighbours, _unitProps, _cutCorners, false); return; } //Natural neighbour current.TryGetWalkableNeighbour(0, direction.z, _unitProps, _neighbours); //Forced neighbours? The left/right is as seen from a normal view of the grid, i.e. not seen from the direction of movement (well direction bottom up) if (_cutCorners) { var nLeft = current.GetNeighbour(-1, 0); if (nLeft != null && !nLeft.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(-1, direction.z, _unitProps, _neighbours); } var nRight = current.GetNeighbour(1, 0); if (nRight != null && !nRight.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(1, direction.z, _unitProps, _neighbours); } } else { var nLeftDown = current.GetNeighbour(-1, -direction.z); if (nLeftDown != null && !nLeftDown.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(-1, 0, _unitProps, _neighbours); current.TryGetWalkableNeighbour(-1, direction.z, _unitProps, _neighbours); } var nRightDown = current.GetNeighbour(1, -direction.z); if (nRightDown != null && !nRightDown.IsWalkableFromAllDirections(_unitProps)) { current.TryGetWalkableNeighbour(1, 0, _unitProps, _neighbours); current.TryGetWalkableNeighbour(1, direction.z, _unitProps, _neighbours); } } } }
private bool HasForcedNeighbour(IPathNode current, VectorXZ direction) { if (current.hasVirtualNeighbour) { return(true); } bool hasForced = false; if (direction.x != 0) { if (direction.z != 0) { if (_cutCorners) { var nLeft = current.GetNeighbour(-direction.x, 0); if (nLeft != null && !nLeft.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(-direction.x, direction.z); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } var nDown = current.GetNeighbour(0, -direction.z); if (nDown != null && !nDown.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(direction.x, -direction.z); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } } else { return(false); } } else { if (_cutCorners) { var nUp = current.GetNeighbour(0, 1); if (nUp != null && !nUp.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(direction.x, 1); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } var nDown = current.GetNeighbour(0, -1); if (nDown != null && !nDown.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(direction.x, -1); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } } else { var nUpBack = current.GetNeighbour(-direction.x, 1); if (nUpBack != null && !nUpBack.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(0, 1); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } var nDownBack = current.GetNeighbour(-direction.x, -1); if (nDownBack != null && !nDownBack.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(0, -1); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } } } } else { if (_cutCorners) { var nLeft = current.GetNeighbour(-1, 0); if (nLeft != null && !nLeft.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(-1, direction.z); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } var nRight = current.GetNeighbour(1, 0); if (nRight != null && !nRight.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(1, direction.z); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } } else { var nLeftDown = current.GetNeighbour(-1, -direction.z); if (nLeftDown != null && !nLeftDown.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(-1, 0); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } var nRightDown = current.GetNeighbour(1, -direction.z); if (nRightDown != null && !nRightDown.IsWalkableFromAllDirections(_unitProps)) { var fn = current.GetNeighbour(1, 0); hasForced |= (fn != null && fn.IsWalkableFromWithClearance(current, _unitProps)); } } } return(hasForced); }
/// <summary> /// Sets the waypoint's position and rotation to that of the given transform. /// </summary> public void Initialize(Transform newWaypointTransform) { _position = new VectorXZ(newWaypointTransform.position.x, newWaypointTransform.position.z); _rotation = newWaypointTransform.rotation.eulerAngles; }