Support Forum

Graph Update Scene for 2D with Polygon Collider for GridGraphs

If anyone has encountered problems with the graph update scene with polygon collider especially for 2D isometric. You can use this.

public class GraphUpdateScene2D : GraphModifier
	{
		/// <summary>
		/// Penalty to add to nodes.
		/// Usually you need quite large values, at least 1000-10000. A higher penalty means that agents will try to avoid those nodes more.
		///
		/// Be careful when setting negative values since if a node gets a negative penalty it will underflow and instead get
		/// really large. In most cases a warning will be logged if that happens.
		///
		/// See: tags (view in online documentation for working links) for another way of applying penalties.
		/// </summary>
		public uint penaltyValue;

		/// <summary>Nodes will be made walkable or unwalkable according to this value if <see cref="modifyWalkability"/> is true</summary>
		public bool setWalkable = true;

		/// <summary>Apply this graph update object whenever a graph is rescanned</summary>
		public bool applyOnScan = true;

		/// <summary>
		/// Should the tags of the nodes be modified.
		/// If enabled, set all nodes' tags to <see cref="setTag"/>
		/// </summary>
		public bool modifyTag;

		[HideInInspector]
		/// <summary>If <see cref="modifyTag"/> is enabled, set all nodes' tags to this value</summary>
		public int setTag;

		public bool firstApplied = false;

		public bool scanOnStart = true;

        private void Start()
        {
            if (!firstApplied && scanOnStart)
            {
				Apply();
            }
        }

        public override void OnPostScan()
		{
			if (applyOnScan) Apply();
		}


		/// <summary>
		/// Updates graphs with a created GUO
		/// representing the polygon of this object and update all graphs using AstarPath.UpdateGraphs.
		/// </summary>
		public void Apply()
		{
			firstApplied = true;
			if (AstarPath.active == null)
            {
				Debug.LogError("There is no AstarPath object in the scene", this);
				return;
            }

			PolygonCollider2D polygonCollider = GetComponent<PolygonCollider2D>();
			if (polygonCollider == null)
            {
				Debug.LogError("There is no PolygonCollider2D attached");
            }
			else
            {
				AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => 
				{
                    NavGraph[] graphs = AstarPath.active.graphs;
                    foreach (NavGraph graph in graphs)
                    {
						GridGraph gg = (GridGraph)graph;
						if (gg == null) { continue; }
						for (int z = 0; z < gg.depth; z++)
                        {
							for (int x = 0; x < gg.width; x++)
                            {
								var node = gg.GetNode(x, z);
								Vector3 pos = (Vector3)node.position;
								if (polygonCollider.OverlapPoint(new Vector2(pos.x, pos.y)))
                                {
									node.Penalty = penaltyValue;
									node.Walkable = setWalkable;
									if (modifyTag)
										node.Tag = (uint)setTag;
                                }
                            }
                        }
                    }
                }));
            }
		}
	}

Then put this in an Editor folder.

[CustomEditor(typeof(GraphUpdateScene2D))]
	[CanEditMultipleObjects]
	public class GraphUpdateSceneEditor2D : EditorBase
	{
		protected override void Inspector()
		{
			base.Inspector();
			EditorGUI.BeginChangeCheck();

			EditorGUI.indentLevel = 0;

			DrawTagField();

			EditorGUILayout.Separator();

			if (EditorGUI.EndChangeCheck())
			{
				EditorUtility.SetDirty(target);
				// Repaint the scene view if necessary
				// if (!Application.isPlaying || EditorApplication.isPaused) SceneView.RepaintAll();
			}
		}

		void DrawTagField()
		{
			var tagValue = FindProperty("setTag");
			EditorGUI.indentLevel++;
			EditorGUI.showMixedValue = tagValue.hasMultipleDifferentValues;
			EditorGUI.BeginChangeCheck();
			var newTag = EditorGUILayoutx.TagField("Tag Value", tagValue.intValue, () => AstarPathEditor.EditTags());
			if (EditorGUI.EndChangeCheck())
			{
				tagValue.intValue = newTag;
			}

			if (GUILayout.Button("Tags can be used to restrict which units can walk on what ground. Click here for more info", "HelpBox"))
			{
			}
			EditorGUI.indentLevel--;
		}
	}

You can now make more complex weighted paths like these. Hope this helps.