protected override void DrawCollisionEditor (GraphCollision collision) {
			base.DrawCollisionEditor(collision);

			if (collision.thickRaycast) {
				EditorGUILayout.HelpBox("Note: Thick raycast cannot be used with this graph type", MessageType.Error);
			}
		}
        public override void Scan()
        {
            scans++;

            if (nodeSize <= 0) {
                return;
            }

            GenerateMatrix ();

            if (width > 1024 || depth > 1024) {
                Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
                return;
            }

            //GenerateBounds ();

            /*neighbourOffsets = new int[8] {
                -width-1,-width,-width+1,
                -1,1,
                width-1,width,width+1
            }*/

            SetUpOffsetsAndCosts ();

            //GridNode.RemoveGridGraph (this);

            int gridIndex = LevelGridNode.SetGridGraph (this);

            //graphNodes = new LevelGridNode[width*depth];

            //nodes = CreateNodes (width*depth);
            //graphNodes = nodes as LevelGridNode[];

            maxClimb = Mathf.Clamp (maxClimb,0,characterHeight);

            LinkedLevelCell[] linkedCells = new LinkedLevelCell[width*depth];

            if (collision == null) {
                collision = new GraphCollision ();
            }
            collision.Initialize (matrix,nodeSize);

            for (int z = 0; z < depth; z ++) {
                for (int x = 0; x < width; x++) {

                    linkedCells[z*width+x] = new LinkedLevelCell ();

                    LinkedLevelCell llc = linkedCells[z*width+x];
                    //GridNode node = graphNodes[z*width+x];//new LevelGridNode ();

                    //node.SetIndex (z*width+x);

                    Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));

                    RaycastHit[] hits = collision.CheckHeightAll (pos);

                    //Sort the hits based on distance with bubble sort (fast enough)
                    //Furthest away first (i.e lowest nodes in the graph)
                    /*bool changed = true;
                    while (changed) {
                        changed = false;
                        for (int i=0;i<hits.Length-1;i++) {
                            if (hits[i].distance < hits[i+1].distance) {
                                RaycastHit tmp = hits[i];
                                hits[i] = hits[i+1];
                                hits[i+1] = tmp;
                                changed = true;
                            }
                        }
                    }*/

                    for (int i=0;i<hits.Length/2;i++) {
                        RaycastHit tmp = hits[i];

                        hits[i] = hits[hits.Length-1-i];
                        hits[hits.Length-1-i] = tmp;
                    }

                    if (hits.Length > 0) {

                        //lln.position = hits[0].point;
                        //lln.walkable = collision.Check (lln.position);

                        /*LinkedLevelNode lln = new LinkedLevelNode ();
                        lln.position = hits[0].point;
                        lln.walkable = collision.Check (lln.position);
                        llc.first = lln;*/

                        LinkedLevelNode lln = null;

                        for (int i=0;i<hits.Length;i++) {

                            LinkedLevelNode tmp = new LinkedLevelNode ();
                            tmp.position = hits[i].point;

                            if (lln != null) {
                                /** \todo Use hit.distance instead */
                                if (tmp.position.y - lln.position.y <= mergeSpanRange) {
                                    //if (tmp.position.y > lln.position.y) {
                                        lln.position = tmp.position;
                                        lln.hit = hits[i];
                                        lln.walkable = collision.Check (tmp.position);
                                    //}
                                    continue;
                                }
                            }

                            tmp.walkable = collision.Check (tmp.position);
                            tmp.hit = hits[i];
                            tmp.height = float.PositiveInfinity;

                            if (llc.first == null) {
                                llc.first = tmp;
                                lln = tmp;
                            } else {
                                lln.next = tmp;

                                lln.height = tmp.position.y - lln.position.y;
                                lln = lln.next;
                            }

                        }
                    } else {
                        LinkedLevelNode lln = new LinkedLevelNode ();
                        lln.position = pos;
                        lln.height = float.PositiveInfinity;
                        lln.walkable = !collision.unwalkableWhenNoGround;
                        llc.first = lln;
                    }

                    //node.penalty = 0;//Mathf.RoundToInt (Random.value*100);

                    //node.walkable = collision.Check (node.position);

                    //node.SetGridIndex (gridIndex);
                }
            }

            int spanCount = 0;
            layerCount = 0;
            //Count the total number of nodes in the graph
            for (int z = 0; z < depth; z ++) {
                for (int x = 0; x < width; x++) {

                    LinkedLevelCell llc = linkedCells[z*width+x];

                    LinkedLevelNode lln = llc.first;
                    int cellCount = 0;
                    //Loop through all nodes in this cell
                    do {
                        cellCount++;
                        spanCount++;
                        lln = lln.next;
                    } while (lln != null);

                    layerCount = cellCount > layerCount ? cellCount : layerCount;
                }
            }

            if (layerCount > LevelGridNode.MaxLayerCount) {
                Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")");
                return;
            }

            //Create all nodes
            nodes = CreateNodes (width*depth*layerCount);

            int nodeIndex = 0;

            //Max slope in cosinus
            float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);

            for (int z = 0; z < depth; z++) {
                for (int x = 0; x < width; x++) {

                    LinkedLevelCell llc = linkedCells[z*width+x];
                    LinkedLevelNode lln = llc.first;

                    llc.index = nodeIndex;

                    int count = 0;
                    int layerIndex = 0;
                    do {
                        LevelGridNode node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode;
            #if ASTAR_SET_LEVELGRIDNODE_HEIGHT
                        node.height = lln.height;
            #endif
                        node.position = (Int3)lln.position;
                        node.walkable = lln.walkable;
                        node.Bit15 = node.walkable;

                        //Adjust penalty based on the surface slope
                        if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) {
                            //Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
                            float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up);

                            //Add penalty based on normal
                            if (penaltyAngle) {
                                node.penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor);
                            }

                            //Check if the slope is flat enough to stand on
                            if (angle < cosAngle) {
                                node.walkable = false;
                            }
                        }

                        node.SetIndex (z*width+x);
                        //node.nodeOffset = count;
                        if (lln.height < characterHeight) {
                            node.walkable = false;
                        }
                        nodeIndex++;
                        count++;
                        lln = lln.next;
                        layerIndex++;
                    } while (lln != null);

                    for (;layerIndex<layerCount;layerIndex++) {
                        nodes[z*width+x + width*depth*layerIndex] = null;
                    }

                    llc.count = count;
                }
            }

            nodeIndex = 0;

            nodeCellIndices = new int[linkedCells.Length];

            for (int z = 0; z < depth; z ++) {
                for (int x = 0; x < width; x++) {

                    /*LinkedLevelCell llc = linkedCells[z*width+x];
                    LinkedLevelNode lln = llc.first;

                    nodeCellIndices[z*width+x] = llc.index;

                    do {
                        LevelGridNode node = (LevelGridNode)nodes[nodeIndex];

                        CalculateConnections (nodes,linkedCells,node,x,z,n);
                        nodeIndex++;
                        lln = lln.next;
                    } while (lln != null);*/

                    for (int i=0;i<layerCount;i++) {
                        Node node = nodes[z*width+x + width*depth*i];
                        CalculateConnections (nodes,node,x,z,i);
                    }
                }
            }

            for (int i=0;i<nodes.Length;i++) {
                LevelGridNode lgn = nodes[i] as LevelGridNode;
                if (lgn == null) continue;

                UpdatePenalty (lgn);

                lgn.SetGridIndex (gridIndex);

                //Set the node to be unwalkable if it hasn't got any connections
                if (!lgn.HasAnyGridConnections ()) {
                    lgn.walkable = false;
                }
            }
                    /*GridNode node = graphNodes[z*width+x];

                    CalculateConnections (graphNodes,x,z,node);

                    if (z == 5 && x == 5) {
                        int index = z*width+x;
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
                        Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
                    }*/
                //}
            //}

            ErodeWalkableArea (0,0,width,depth);
        }
Example #3
0
        public void DeSerializeSettings(AstarSerializer serializer)
        {
            //width = (int)serializer.GetValue ("Width",typeof(int));
            //depth = (int)serializer.GetValue ("Depth",typeof(int));
            //height = (float)serializer.GetValue ("Height",typeof(float));

            unclampedSize = (Vector2)serializer.GetValue ("unclampedSize",typeof(Vector2));

            cutCorners = (bool)serializer.GetValue ("cutCorners",typeof(bool));
            neighbours = (NumNeighbours)serializer.GetValue ("neighbours",typeof(int));

            rotation = (Vector3)serializer.GetValue ("rotation",typeof(Vector3));

            nodeSize = (float)serializer.GetValue ("nodeSize",typeof(float));

            collision = (GraphCollision)serializer.GetValue ("collision",typeof(GraphCollision));

            center = (Vector3)serializer.GetValue ("center",typeof(Vector3));

            maxClimb = (float)serializer.GetValue ("maxClimb",typeof(float));
            maxClimbAxis = (int)serializer.GetValue ("maxClimbAxis",typeof(int),1);
            maxSlope = (float)serializer.GetValue ("maxSlope",typeof(float),90.0F);

            erodeIterations = (int)serializer.GetValue ("erodeIterations",typeof(int));

            penaltyAngle = 			(bool)serializer.GetValue ("penaltyAngle",typeof(bool));
            penaltyAngleFactor = 	(float)serializer.GetValue ("penaltyAngleFactor",typeof(float));
            penaltyPosition = 		(bool)serializer.GetValue ("penaltyPosition",typeof(bool));
            penaltyPositionOffset = (float)serializer.GetValue ("penaltyPositionOffset",typeof(float));
            penaltyPositionFactor = (float)serializer.GetValue ("penaltyPositionFactor",typeof(float));

            aspectRatio = (float)serializer.GetValue ("aspectRatio",typeof(float),1F);

            textureData			=	serializer.GetValue ("textureData",typeof(TextureData)) as TextureData;
            if (textureData == null) textureData = new TextureData ();

            #if UNITY_EDITOR
            Matrix4x4 oldMatrix = matrix;
            #endif

            GenerateMatrix ();
            SetUpOffsetsAndCosts ();

            #if UNITY_EDITOR
            if (serializer.onlySaveSettings) {
                if (oldMatrix != matrix && nodes != null) {
                    AstarPath.active.AutoScan ();
                }
            }
            #endif

            //Debug.Log ((string)serializer.GetValue ("SomeString",typeof(string)));
            //Debug.Log ((Bounds)serializer.GetValue ("SomeBounds",typeof(Bounds)));
        }
Example #4
0
    /** Draws the inspector for a \link Pathfinding.GraphCollision GraphCollision class \endlink */
    public void DrawCollisionEditor(GraphCollision collision)
    {
        if (collision == null) {
            collision = new GraphCollision ();
        }

        /*GUILayout.Space (5);
        Rect r = EditorGUILayout.BeginVertical (AstarPathEditor.graphBoxStyle);
        GUI.Box (r,"",AstarPathEditor.graphBoxStyle);
        GUILayout.Space (2);*/
        Separator ();

        /*GUILayout.BeginHorizontal ();
        GUIStyle boxHeader = AstarPathEditor.astarSkin.FindStyle ("CollisionHeader");
        GUILayout.Label ("Collision testing",boxHeader);
        collision.collisionCheck = GUILayout.Toggle (collision.collisionCheck,"");

        bool preEnabledRoot = GUI.enabled;
        GUI.enabled = collision.collisionCheck;
        GUILayout.EndHorizontal ();*/
        collision.collisionCheck = ToggleGroup ("Collision testing",collision.collisionCheck);
        bool preEnabledRoot = GUI.enabled;
        GUI.enabled = collision.collisionCheck;

        //GUILayout.BeginHorizontal ();
        collision.type = (ColliderType)EditorGUILayout.EnumPopup("Collider type",collision.type);
        //new string[3] {"Sphere","Capsule","Ray"}

        bool preEnabled = GUI.enabled;
        if (collision.type != ColliderType.Capsule && collision.type != ColliderType.Sphere) {
            GUI.enabled = false;
        }
        collision.diameter = EditorGUILayout.FloatField (new GUIContent ("Diameter","Diameter of the capsule of sphere where 1 equals one node"),collision.diameter);

        GUI.enabled = preEnabled;

        if (collision.type != ColliderType.Capsule && collision.type != ColliderType.Ray) {
            GUI.enabled = false;
        }
        collision.height = EditorGUILayout.FloatField (new GUIContent ("Height/Length","Height of cylinder of length of ray in world units"),collision.height);
        GUI.enabled = preEnabled;

        collision.collisionOffset = EditorGUILayout.FloatField (new GUIContent("Offset","Offset upwards from the node. Can be used so obstacles can be used as ground and as obstacles for lower nodes"),collision.collisionOffset);

        //collision.mask = 1 << EditorGUILayout.LayerField ("Mask",Mathf.Clamp ((int)Mathf.Log (collision.mask,2),0,31));

        collision.mask = EditorGUILayoutx.LayerMaskField ("Mask",collision.mask);

        GUILayout.Space (2);

        GUI.enabled = preEnabledRoot;

        collision.heightCheck = ToggleGroup ("Height testing",collision.heightCheck);
        GUI.enabled = collision.heightCheck && GUI.enabled;
        /*GUILayout.BeginHorizontal ();
        GUILayout.Label ("Height testing",boxHeader);
        collision.heightCheck = GUILayout.Toggle (collision.heightCheck,"");
        GUI.enabled = collision.heightCheck;
        GUILayout.EndHorizontal ();*/

        collision.fromHeight = EditorGUILayout.FloatField (new GUIContent ("Ray length","The height from which to check for ground"),collision.fromHeight);

        collision.heightMask = EditorGUILayoutx.LayerMaskField ("Mask",collision.heightMask);
        //collision.heightMask = 1 << EditorGUILayout.LayerField ("Mask",Mathf.Clamp ((int)Mathf.Log (collision.heightMask,2),0,31));

        collision.thickRaycast = EditorGUILayout.Toggle (new GUIContent ("Thick Raycast", "Use a thick line instead of a thin line"),collision.thickRaycast);

        editor.GUILayoutx.BeginFadeArea (collision.thickRaycast,"thickRaycastDiameter");

        if (editor.GUILayoutx.DrawID ("thickRaycastDiameter")) {
            EditorGUI.indentLevel++;
            collision.thickRaycastDiameter = EditorGUILayout.FloatField (new GUIContent ("Diameter","Diameter of the thick raycast"),collision.thickRaycastDiameter);
            EditorGUI.indentLevel--;
        }

        editor.GUILayoutx.EndFadeArea ();

        collision.unwalkableWhenNoGround = EditorGUILayout.Toggle (new GUIContent ("Unwalkable when no ground","Make nodes unwalkable when no ground was found with the height raycast. If height raycast is turned off, this doesn't affect anything"), collision.unwalkableWhenNoGround);

        GUI.enabled = preEnabledRoot;

        //GUILayout.Space (2);
        //EditorGUILayout.EndVertical ();
        //GUILayout.Space (5);
    }
Example #5
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			AstarPath.OnPostScan += new OnScanDelegate(OnPostScan);

			if (nodeSize <= 0) {
				return;
			}

			// Make sure the matrix is up to date
			GenerateMatrix();

			if (width > 1024 || depth > 1024) {
				Debug.LogError("One of the grid's sides is longer than 1024 nodes");
				return;
			}


			SetUpOffsetsAndCosts();

			// Get the graph index of this graph
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);

			// Set a global reference to this graph so that nodes can find it
			GridNode.SetGridGraph(graphIndex, this);

			// Create all nodes
			nodes = new GridNode[width*depth];
			for (int i = 0; i < nodes.Length; i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}

			// Create and initialize the collision class
			if (collision == null) {
				collision = new GraphCollision();
			}
			collision.Initialize(matrix, nodeSize);


			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					var node = nodes[z*width+x];

					node.NodeInGridIndex = z*width+x;

					// Updates the position of the node
					// and a bunch of other things
					UpdateNodePositionCollision(node, x, z);
				}
			}

			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					var node = nodes[z*width + x];
					// Recalculate connections to other nodes
					CalculateConnections(x, z, node);
				}
			}

			// Apply erosion
			ErodeWalkableArea();
		}
		protected virtual void DrawUse2DPhysics (GraphCollision collision) {
			collision.use2D = EditorGUILayout.Toggle (new GUIContent ("Use 2D Physics", "Use the Physics2D API for collision checking"), collision.use2D );
		}
		/** Draws the inspector for a \link Pathfinding.GraphCollision GraphCollision class \endlink */
		protected virtual void DrawCollisionEditor (GraphCollision collision) {

			collision = collision ?? new GraphCollision ();

			DrawUse2DPhysics (collision);

			collision.collisionCheck = ToggleGroup ("Collision testing",collision.collisionCheck);
			EditorGUI.BeginDisabledGroup(!collision.collisionCheck);

			collision.type = (ColliderType)EditorGUILayout.EnumPopup("Collider type",collision.type);

			EditorGUI.BeginDisabledGroup(collision.type != ColliderType.Capsule && collision.type != ColliderType.Sphere);
			collision.diameter = EditorGUILayout.FloatField (new GUIContent ("Diameter","Diameter of the capsule or sphere. 1 equals one node width"),collision.diameter);
			EditorGUI.EndDisabledGroup();

			EditorGUI.BeginDisabledGroup(collision.type != ColliderType.Capsule && collision.type != ColliderType.Ray);
			collision.height = EditorGUILayout.FloatField (new GUIContent ("Height/Length","Height of cylinder or length of ray in world units"),collision.height);
			EditorGUI.EndDisabledGroup();

			collision.collisionOffset = EditorGUILayout.FloatField (new GUIContent("Offset","Offset upwards from the node. Can be used so that obstacles can be used as ground and at the same time as obstacles for lower positioned nodes"),collision.collisionOffset);

			collision.mask = EditorGUILayoutx.LayerMaskField ("Mask",collision.mask);

			EditorGUI.EndDisabledGroup();

			GUILayout.Space (2);


			EditorGUI.BeginDisabledGroup(collision.use2D);
			collision.heightCheck = ToggleGroup ("Height testing",collision.heightCheck);
			EditorGUI.BeginDisabledGroup(!collision.heightCheck);

			collision.fromHeight = EditorGUILayout.FloatField (new GUIContent ("Ray length","The height from which to check for ground"),collision.fromHeight);

			collision.heightMask = EditorGUILayoutx.LayerMaskField ("Mask",collision.heightMask);

			collision.thickRaycast = EditorGUILayout.Toggle (new GUIContent ("Thick Raycast", "Use a thick line instead of a thin line"),collision.thickRaycast);

			if (collision.thickRaycast) {
				EditorGUI.indentLevel++;
				collision.thickRaycastDiameter = EditorGUILayout.FloatField (new GUIContent ("Diameter","Diameter of the thick raycast"),collision.thickRaycastDiameter);
				EditorGUI.indentLevel--;
			}

			collision.unwalkableWhenNoGround = EditorGUILayout.Toggle (new GUIContent ("Unwalkable when no ground","Make nodes unwalkable when no ground was found with the height raycast. If height raycast is turned off, this doesn't affect anything"), collision.unwalkableWhenNoGround);

			EditorGUI.EndDisabledGroup();
			EditorGUI.EndDisabledGroup();
		}
Example #8
0
 protected virtual void DrawUse2DPhysics(GraphCollision collision)
 {
     collision.use2D = EditorGUILayout.Toggle(new GUIContent("Use 2D Physics", "Use the Physics2D API for collision checking"), collision.use2D);
 }
		public override IEnumerable<Progress> ScanInternal () {

			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);

			if (nodeSize <= 0) {
				yield break;
			}

			// Make sure the matrix is up to date
			GenerateMatrix ();

			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				yield break;
			}


			SetUpOffsetsAndCosts ();

			// Get the graph index of this graph
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);

			// Set a global reference to this graph so that nodes can find it
			GridNode.SetGridGraph (graphIndex,this);

			yield return new Progress(0.05f, "Creating nodes");

			// Create all nodes
			nodes = new GridNode[width*depth];
			for (int i = 0; i < nodes.Length; i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}

			// Create and initialize the collision class
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);


			int progressCounter = 0;

			const int YieldEveryNNodes = 1000;

			for (int z = 0; z < depth; z ++) {
				// Yield with a progress value at most every N nodes
				if (progressCounter >= YieldEveryNNodes) {
					progressCounter = 0;
					yield return new Progress(Mathf.Lerp(0.1f,0.7f,z/(float)depth), "Calculating positions");
				}

				progressCounter += width;

				for (int x = 0; x < width; x++) {

					var node = nodes[z*width+x];

					node.NodeInGridIndex = z*width+x;

					// Updates the position of the node
					// and a bunch of other things
					UpdateNodePositionCollision (node,x,z);

				}
			}

			for (int z = 0; z < depth; z++) {
				// Yield with a progress value at most every N nodes
				if (progressCounter >= YieldEveryNNodes) {
					progressCounter = 0;
					yield return new Progress(Mathf.Lerp(0.1f,0.7f,z/(float)depth), "Calculating connections");
				}

				for (int x = 0; x < width; x++) {
					var node = nodes[z*width + x];
					// Recalculate connections to other nodes
					CalculateConnections(x, z, node);
				}
			}

			yield return new Progress(0.95f, "Calculating erosion");

			// Apply erosion
			ErodeWalkableArea ();
		}
		protected override void DrawUse2DPhysics (GraphCollision collision) {
			// 2D physics does not make sense for a layered grid graph
			collision.use2D = false;
		}
Example #11
0
        public override void Scan()
        {
            AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);

            scanns++;

            if (nodeSize <= 0) {
                return;
            }

            GenerateMatrix ();

            if (width > 1024 || depth > 1024) {
                Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
                return;
            }

            //GenerateBounds ();

            /*neighbourOffsets = new int[8] {
                -width-1,-width,-width+1,
                -1,1,
                width-1,width,width+1
            }*/

            SetUpOffsetsAndCosts ();

            //GridNode.RemoveGridGraph (this);

            int gridIndex = GridNode.SetGridGraph (this);

            //graphNodes = new GridNode[width*depth];

            nodes = CreateNodes (width*depth);
            graphNodes = nodes as GridNode[];

            if (collision == null) {
                collision = new GraphCollision ();
            }
            collision.Initialize (matrix,nodeSize);

            //Max slope in cosinus
            //float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);

            for (int z = 0; z < depth; z ++) {
                for (int x = 0; x < width; x++) {

                    GridNode node = graphNodes[z*width+x];//new GridNode ();

                    node.SetIndex (z*width+x);

                    UpdateNodePositionCollision (node,x,z);

                    /*node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));

                    RaycastHit hit;

                    bool walkable = true;

                    node.position = collision.CheckHeight (node.position, out hit, out walkable);

                    node.penalty = 0;//Mathf.RoundToInt (Random.value*100);

                    //Check if the node is on a slope steeper than permitted
                    if (walkable && useRaycastNormal && collision.heightCheck) {

                        if (hit.normal != Vector3.zero) {
                            //Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
                            float angle = Vector3.Dot (hit.normal.normalized,Vector3.up);

                            if (angle < cosAngle) {
                                walkable = false;
                            }
                        }
                    }

                    //If the walkable flag has already been set to false, there is no point in checking for it again
                    if (walkable) {
                        node.walkable = collision.Check (node.position);
                    } else {
                        node.walkable = walkable;
                    }*/

                    node.SetGridIndex (gridIndex);
                }
            }

            for (int z = 0; z < depth; z ++) {
                for (int x = 0; x < width; x++) {

                    GridNode node = graphNodes[z*width+x];

                    CalculateConnections (graphNodes,x,z,node);

                }
            }

            ErodeWalkableArea ();
            //Assign the nodes to the main storage

            //startIndex = AstarPath.active.AssignNodes (graphNodes);
            //endIndex = startIndex+graphNodes.Length;
        }
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

#if !ASTAR_JPS
			if (this.useJumpPointSearch) {
				Debug.LogError ("Trying to use Jump Point Search, but support for it is not enabled. Please enable it in the inspector (Grid Graph settings).");
			}
#endif
			
			SetUpOffsetsAndCosts ();
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);

			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			textureData.Initialize ();
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
					textureData.Apply (node,x,z);
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
#if ASTARDEBUG
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}
#endif
				}
			}
			
			
			ErodeWalkableArea ();
		}
Example #13
0
    // sets up pathfinding
    // To get walking/flying working with dynamic room generation, some complexity was required
    public void AddGraph()
    {
        AstarData data = AstarPath.active.astarData;
        // This creates a Grid Graph
        GridGraph gg = data.AddGraph(typeof(GridGraph)) as GridGraph;
        // Setup a grid graph with some values
        gg.width = 50;
        gg.depth = 40;
        gg.center = transform.position + new Vector3(0, -5, 0);
        // Updates internal size from the above values
        gg.UpdateSizeFromWidthDepth();

        GraphCollision gc = new GraphCollision();
        gc.collisionCheck = true;
        gc.heightCheck = true;
        gc.diameter = 2F;
        gc.heightMask = LayerMask.GetMask(new string[] {"Rock","Room","Floor"});
        gc.mask = LayerMask.GetMask(new string[] {"Rock","Room"});
        gg.maxClimb = 8F;
        gg.collision = gc;
    }
Example #14
0
        /// <summary>Draws the inspector for a \link Pathfinding.GraphCollision GraphCollision class \endlink</summary>
        protected virtual void DrawCollisionEditor(GraphCollision collision)
        {
            collision = collision ?? new GraphCollision();

            DrawUse2DPhysics(collision);

            collision.collisionCheck = ToggleGroup("Collision testing", collision.collisionCheck);
            if (collision.collisionCheck)
            {
                string[] colliderOptions = collision.use2D ? new [] { "Circle", "Point" } : new [] { "Sphere", "Capsule", "Ray" };
                int[]    colliderValues  = collision.use2D ? new [] { 0, 2 } : new [] { 0, 1, 2 };
                // In 2D the Circle (Sphere) mode will replace both the Sphere and the Capsule modes
                // However make sure that the original value is still stored in the grid graph in case the user changes back to the 3D mode in the inspector.
                var tp = collision.type;
                if (tp == ColliderType.Capsule && collision.use2D)
                {
                    tp = ColliderType.Sphere;
                }
                EditorGUI.BeginChangeCheck();
                tp = (ColliderType)EditorGUILayout.IntPopup("Collider type", (int)tp, colliderOptions, colliderValues);
                if (EditorGUI.EndChangeCheck())
                {
                    collision.type = tp;
                }

                // Only spheres and capsules have a diameter
                if (collision.type == ColliderType.Capsule || collision.type == ColliderType.Sphere)
                {
                    collision.diameter = EditorGUILayout.FloatField(new GUIContent("Diameter", "Diameter of the capsule or sphere. 1 equals one node width"), collision.diameter);
                }

                if (!collision.use2D)
                {
                    if (collision.type == ColliderType.Capsule || collision.type == ColliderType.Ray)
                    {
                        collision.height = EditorGUILayout.FloatField(new GUIContent("Height/Length", "Height of cylinder or length of ray in world units"), collision.height);
                    }

                    collision.collisionOffset = EditorGUILayout.FloatField(new GUIContent("Offset", "Offset upwards from the node. Can be used so that obstacles can be used as ground and at the same time as obstacles for lower positioned nodes"), collision.collisionOffset);
                }

                collision.mask = EditorGUILayoutx.LayerMaskField("Obstacle Layer Mask", collision.mask);

                DrawCollisionPreview(collision);
            }

            GUILayout.Space(2);

            if (collision.use2D)
            {
                EditorGUI.BeginDisabledGroup(collision.use2D);
                ToggleGroup("Height testing", false);
                EditorGUI.EndDisabledGroup();
            }
            else
            {
                collision.heightCheck = ToggleGroup("Height testing", collision.heightCheck);
                if (collision.heightCheck)
                {
                    collision.fromHeight = EditorGUILayout.FloatField(new GUIContent("Ray length", "The height from which to check for ground"), collision.fromHeight);

                    collision.heightMask = EditorGUILayoutx.LayerMaskField("Mask", collision.heightMask);

                    collision.thickRaycast = EditorGUILayout.Toggle(new GUIContent("Thick Raycast", "Use a thick line instead of a thin line"), collision.thickRaycast);

                    if (collision.thickRaycast)
                    {
                        EditorGUI.indentLevel++;
                        collision.thickRaycastDiameter = EditorGUILayout.FloatField(new GUIContent("Diameter", "Diameter of the thick raycast"), collision.thickRaycastDiameter);
                        EditorGUI.indentLevel--;
                    }

                    collision.unwalkableWhenNoGround = EditorGUILayout.Toggle(new GUIContent("Unwalkable when no ground", "Make nodes unwalkable when no ground was found with the height raycast. If height raycast is turned off, this doesn't affect anything"), collision.unwalkableWhenNoGround);
                }
            }
        }
Example #15
0
		public GridGraph () {
			unclampedSize = new Vector2 (10,10);
			nodeSize = 1F;
			collision = new GraphCollision ();
		}
Example #16
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

			
			SetUpOffsetsAndCosts ();
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);

			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
				}
			}
			
			
			ErodeWalkableArea ();
		}
Example #17
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}
			
			//GenerateBounds ();
			
			/*neighbourOffsets = new int[8] {
				-width-1,-width,-width+1,
				-1,1,
				width-1,width,width+1
			}*/
			
			SetUpOffsetsAndCosts ();
			
			//GridNode.RemoveGridGraph (this);
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);
			
			//graphNodes = new GridNode[width*depth];
			
			//nodes = CreateNodes (width*depth);
			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			textureData.Initialize ();
			
			//Max slope in cosinus
			//float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];//new GridNode ();
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
					textureData.Apply (node,x,z);
					
					/*node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));
					
					RaycastHit hit;
					
					bool walkable = true;
					
					node.position = collision.CheckHeight (node.position, out hit, out walkable);
					
					node.penalty = 0;//Mathf.RoundToInt (Random.value*100);
					
					//Check if the node is on a slope steeper than permitted
					if (walkable && useRaycastNormal && collision.heightCheck) {
						
						if (hit.normal != Vector3.zero) {
							//Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
							float angle = Vector3.Dot (hit.normal.normalized,Vector3.up);
							
							if (angle < cosAngle) {
								walkable = false;
							}
						}
					}
					
					//If the walkable flag has already been set to false, there is no point in checking for it again
					if (walkable) {
						node.walkable = collision.Check (node.position);
					} else {
						node.walkable = walkable;
					}*/
					
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
#if ASTARDEBUG
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}
#endif
				}
			}
			
			
			ErodeWalkableArea ();
			//Assign the nodes to the main storage
			
			//startIndex = AstarPath.active.AssignNodes (graphNodes);
			//endIndex = startIndex+graphNodes.Length;
		}
Example #18
0
 protected override void DrawUse2DPhysics(GraphCollision collision)
 {
     // 2D physics does not make sense for a layered grid graph
     collision.use2D = false;
 }