ClosestOnNode EndModifier, while ignoring Y-position (normal Grid Graph)


#1

Is it possible to setup normal, non multi-layered grid graph, using start/end modifier #ClosestOnNode, that does ignore the node height/y-axis position?

I’m working on underwater, 3D environment. Pathing works fine for Original start/end modifier, however, if i’m using Original start/end modifier, the seeker doesn’t seem to care about Areas, and just creates paths between Areas that are not connected/obstructed (and it’s visible on graph). So i’m using ClosestOnNode, but that doesn’t work in 3D.

Any solution? Either by enabling/hacking ClosestOnNode to somehow ignore y-position, or forcing seeker with Original start/end modifier to check if the areas it path from and to are connected?


#2

What do you mean by that it doesn’t work in 3D? Can you show a screenshot?


#3

ClosestOnNode works, well, as intended - it creates the path point on the node (so if the ground grid graph is at height 0, the node point position is also 0), closest to defined point in argument. However, i would like to clamp it only in X and Z position, so it still checks if there is path between (possibly obstructed) areas, while allowing free movement in Y axis.

So something between Original start/end position (free floating in 3D enviroment with ground/obstacles avoidance), and ClosestOnNode (that still checks if the start/end areas are connected). Is it possible to achieve something like that in A*PP?


#4

That’s crude but hopefully helpful diagram of what i mean:


#5

Ah. I see.

If you always have just a single y coordinate, then you could for example create a custom modifier to tweak the path after all modifiers are finished.
If you are using a custom movement script (not e.g AIPath) you could also just do the tweaking in the OnPathComplete method which is called when the path has just been calculated.

using UnityEngine;
using System.Collections.Generic;
using Pathfinding;

public class FixedYModifier : MonoModifier {
	public override int Order { get { return 60; } }

	public override void Apply (Path path) {
		if (path.error || path.vectorPath == null) {
			return;
		}

		for (int i = 0; i < path.vectorPath.Count; i++) {
			path.vectorPath[i].y = path.originalEndPoint.y;
		}
	}
}

Attach this script to the same GameObject as the one with the Seeker component.


#6

Ok, thank You so much, i’ll check the custom modifier approach asap! Btw, here is screenshot with pathing between two, not connected areas. Is it possible to somehow force checking for connections between areas like here? (It’s path before applying any modifier i believe)


#7

Hi

That’s with the Original setting I presume?
The Original setting will just set the endpoint of the path to the requested endpoint of the path regardless of if it could be reached or not. Usually you want to use ClosestOnNode (this is the case also when using the modifier code above as the ClosestOnNode mode will adjust the x and z coordinates properly).


#8

Yes, exactly. I see, thank You so very, very much for such quick and detailed answers, i hope i’ll use the A*PP in my final product. Thank You again!


#9

I don’t know what i’m missing, but both originalEndPoint and originalStartPoint are not part of path class. I know they are part of ABPath, etc - do i need to cast the path from Apply into ABPath before i can reach the originalEnd/StartPoint values like below?

path.vectorPath[i].y = (path as ABPath).originalEndPoint.y;

Is there better performance-wise method to get those values?


#10

Ah. Right. Forgot that only existed on ABPath. Yes that’s what you have to do.
Perhaps more perfomantly as

using UnityEngine;
using System.Collections.Generic;
using Pathfinding;

public class FixedYModifier : MonoModifier {
	public override int Order { get { return 60; } }

	public override void Apply (Path p) {
		var path = p as ABPath;
		if (path == null || path.error || path.vectorPath == null) {
			return;
		}

		for (int i = 0; i < path.vectorPath.Count; i++) {
			path.vectorPath[i].y = path.originalEndPoint.y;
		}
	}
}