/// <summary> /// True if the node has any blocked connections. /// For 4 and 8 neighbours the 4 axis aligned connections will be checked. /// For 6 neighbours all 6 neighbours will be checked. /// /// Internal method used for erosion. /// </summary> /// bool HandingErosionOfOfAnyFalseConnections(GridGraphNode node) { // Check the 6 hexagonal connections if (neighbours == NeighboursNumType.Six) { for (int i = 0; i < 6; i++) { if (!HasConnectionOfNode(node, hexagonNeighbourNodeIndices[i])) { return(true); } } } else { // Check the four axis aligned connections for (int i = 0; i < 4; i++) { if (!HasConnectionOfNode(node, i)) { return(true); } } } return(false); }
/// <summary> /// 处理单个节点的图层冲突信息 /// </summary> /// <param name="node"></param> /// <param name="x"></param> /// <param name="z"></param> public void HandingCollisonOfSingleNode(GridGraphNode node, int width, int depth) { float offestNum = 0.5f; node.position = (Int3)(Matrix.MultiplyPoint3x4(new Vector3(width + offestNum, 0, depth + offestNum))); bool walkAble = false; RaycastHit hitInfo; //处理高度和坡度检查 Vector3 position = graphicCollision.CheckHeight((Vector3)node.position, out hitInfo, out walkAble); node.position = (Int3)position; if (walkAble && graphicCollision.heightCheck) { if (hitInfo.normal != Vector3.zero) { float angle = Vector3.Dot(hitInfo.normal.normalized, graphicCollision.graphUp); if (angle < Mathf.Cos(maxSlope * Mathf.Deg2Rad)) { walkAble = false; } } } //检查障碍物 bool checkObstacles = graphicCollision.Check((Vector3)node.position); node.walkAble = checkObstacles && walkAble; // Debug.Log("ConvertedData::" + ConvertedData + ", x::" + x + ", z::" + z + ",node.walkAble::" + node.walkAble); }
public override void OnDrawGizmos(bool drawFlag) { if (!drawFlag || nodes == null || nodes.Length != nodesInWidth * nodesInDepth) { return; } //绘制outLineBound Gizmos.color = Color.white; Gizmos.matrix = outLineBoundMatrix; Gizmos.DrawWireCube(Vector3.zero, new Vector3(gridSize.x, 0, gridSize.y)); Gizmos.matrix = Matrix4x4.identity; //绘制网格走可走区域 // Debug.Log("depth::" + nodesInDepth + ",width::" + nodesInWidth); Gizmos.color = Color.green; for (int depth = 0; depth < nodesInDepth; depth++) { for (int width = 0; width < nodesInWidth; width++) { var node = nodes[depth * nodesInWidth + width]; // Debug.Log("index::" + (depth * nodesInWidth + width) + "node::" + node.nodeIndex + ", depth::" + depth + ", width::" + width + ",node.walkAble::" + node.walkAble); if (!node.walkAble) { continue; } Vector3 position = (Vector3)node.position; for (int i = 0; i < 8; i++) { if (node.GetConnectionInternal(i)) { GridGraphNode other = nodes[node.nodeIndex + neighbourNodeOffsets[i]]; Gizmos.DrawLine(position, (Vector3)other.position); // Debug.Log("connect::" + other.nodeIndex + ".node::" + node.nodeIndex); } } // Debug.Log("node::" + node.nodeIndex + ", depth::" + depth + ", width::" + width + ",node.walkAble::" + node.walkAble ); } } Gizmos.color = Color.blue; for (int i = 0; i < nodes.Length; i++) { if (nodes[i].walkAble) { Gizmos.color = Color.red; } else { Gizmos.color = Color.gray; } Gizmos.DrawCube((Vector3)nodes[i].position, Vector3.one * 0.5f); } }
/// <summary> /// 扫描图形内部 /// </summary> public override void ScanGraphicInternal() { if (nodeSize <= 0) //默认设置为最小数值 { nodeSize = 0.1f; } UpdateBaseArgs(); if (nodesInWidth > 1024) { Debug.LogError("the grid's sides(nodesInWidth) is longer than 1024 nodes!!"); return; } if (nodesInDepth > 1024) { Debug.LogError("the grid's sides(nodesInDepth) is longer than 1024 nodes!!"); return; } //设置偏移值和代价 SetValuesOfOffsetsAndCosts(); //设置当前当前的网格图层对象 GridGraphNode.SetGridNavGraph(this.graphIndex, this); if (nodes != null) { for (int i = 0; i < nodes.Length; i++) { nodes[i].Destory(); } } //创建节点 nodes = new GridGraphNode[nodesInWidth * nodesInDepth]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new GridGraphNode(); nodes[i].graphIndex = this.graphIndex; nodes[i].nodeIndex = i; } //处理图形冲突,高度坡度检查、障碍物等 HandingGraphicCollision(); //处理节点间的连接 HandingNodesConnections(); //处理侵蚀的部分 ErosionNodeOfArea(0, 0, nodesInWidth, nodesInDepth); }
public virtual bool IsValidConnection(GridGraphNode n1, GridGraphNode n2) { if (!n1.walkAble || !n2.walkAble) { return(false); } if (maxDiffPosition > 0 && Mathf.Abs(n1.position[useAxisOfMaxDiffPosition] - n2.position[useAxisOfMaxDiffPosition]) > maxDiffPosition * Int3.Precision) { return(false); } return(true); }
/// <summary> /// 查看节点是否有连接 /// </summary> /// <param name="node"></param> /// <param name="dir"></param> /// <returns></returns> public bool HasConnectionOfNode(GridGraphNode node, int dir) { if (!node.GetConnectionInternal(dir)) { return(false); } if (node.EdgeNode) { //算出当前的index的行列 int nodeIndex = node.nodeIndex; int depth = nodeIndex / nodesInWidth; int width = nodeIndex - depth * nodesInWidth; return(HasConnectionOfNode(nodeIndex, width, depth, dir)); } else { return(true); } }
bool HandingErosionOfOfAnyFalseConnections(GridGraphNode node) { if (neighbours != NeighboursNumType.Six) { for (int i = 0; i < 4; i++) { if (!HasConnectionOfNode(node, i)) { return(true); } } } else { for (int i = 0; i < 6; i++) { if (!HasConnectionOfNode(node, hexagonNeighbourNodeIndices[i])) { return(true); } } } return(false); }
public void HandingCollisonOfSingleNode(GridGraphNode[] nodes, int width, int depth, GridGraphNode node) { node.ResetConnectionsInternal(); //All connections are disabled if the node is not walkable if (!node.walkAble) { return; } int index = node.nodeIndex; if (neighbours == NeighboursNumType.Four || neighbours == NeighboursNumType.Eight) { // Reset the buffer if (buffers == null) { buffers = new int[4]; } else { for (int i = 0; i < 4; i++) { buffers[i] = 0; } } for (int i = 0, j = 3; i < 4; j = i, i++) { int nx = width + neighbourNodeXOffsets[i]; int nz = depth + neighbourNodeZOffsets[i]; if (nx < 0 || nz < 0 || nx >= nodesInWidth || nz >= nodesInDepth) { continue; } var other = nodes[index + neighbourNodeOffsets[i]]; if (IsValidConnection(node, other)) { node.SetConnectionInternal(i, true); // Mark the diagonal/corner adjacent to this connection as used buffers[i]++; buffers[j]++; } else { node.SetConnectionInternal(i, false); } } // Add in the diagonal connections if (neighbours == NeighboursNumType.Eight) { if (cutCornersOfObstacles) { for (int i = 0; i < 4; i++) { // If at least one axis aligned connection // is adjacent to this diagonal, then we can add a connection if (buffers[i] >= 1) { int nx = width + neighbourNodeXOffsets[i + 4]; int nz = depth + neighbourNodeZOffsets[i + 4]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridGraphNode other = nodes[index + neighbourNodeOffsets[i + 4]]; node.SetConnectionInternal(i + 4, IsValidConnection(node, other)); } } } else { for (int i = 0; i < 4; i++) { // If exactly 2 axis aligned connections is adjacent to this connection // then we can add the connection //We don't need to check if it is out of bounds because if both of the other neighbours are inside the bounds this one must be too if (buffers[i] == 2) { GridGraphNode other = nodes[index + neighbourNodeOffsets[i + 4]]; node.SetConnectionInternal(i + 4, IsValidConnection(node, other)); } } } } } else { // Hexagon layout // Loop through all possible neighbours and try to connect to them for (int j = 0; j < hexagonNeighbourNodeIndices.Length; j++) { var i = hexagonNeighbourNodeIndices[j]; int nx = width + neighbourNodeXOffsets[i]; int nz = depth + neighbourNodeZOffsets[i]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } var other = nodes[index + neighbourNodeOffsets[i]]; node.SetConnectionInternal(i, IsValidConnection(node, other)); } } }