Debug brick spawning at incorrect destination position

I am currently writing my own, simpler version of a pathfinding system, which is based on raycasting (as Roblox’s default Pathfinding tends to be very inconsistent, and to elaborate, sometimes it worked as it should, sometimes it yielded NoPath…).

For debugging reasons, I am spawning bricks at the NPC’s current position (which I consider to be on the floor btw, since I later plan on drawing a raycast between that position and the destination’s position - this is being done in the destResult and torsoPos check), and the NPC does walk, however, the problem is that either the selected destination is incorrect, or the debug brick is spawning at the incorrect destination point.

Here is a video that could help visualise what is going on:
streamable. com/uufni4
(^ the regular link is converted to a download link here for some reason lmao)

And here is the path function of the script:

local function path()

	task.wait()

	if stuck.Value == false and debounce == false then

		debounce = true

		-- first pick the destination (Y has to be raycasted. if raycasted destination Y ends up higher than the raycasted torso Y then make the char jump)

		local function part(pos, color)
			local p = Instance.new("Part")
			p.Position = pos
			p.Size = Vector3.new(1,1,1)
			p.Anchored = true
			p.CanCollide = false
			p.CanTouch = false
			p.CanQuery = false
			p.Parent = workspace
			p.Color = color
			game.Debris:AddItem(p, 3)
		end

		local torsoPos = Vector3.new(char.Torso.Position.X, char.Torso.Position.Y - 3, char.Torso.Position.Z)	
		part(torsoPos, Color3.fromRGB(0,255,0))

		local rayOrigin = Vector3.new(char.Torso.Position.X + rollX(), char.Torso.Position.Y + 10, char.Torso.Position.Z + rollZ())	
		local rayDestination = Vector3.new(rayOrigin.X, rayOrigin.Y - 1000, rayOrigin.Z)

		local destResult = workspace:Raycast(rayOrigin, rayDestination)
		if destResult then

			if destResult.Position.Y  - torsoPos.Y > 3 then -- mb draw a raycast and find the intersection point so it jumps right before that point???
				print("Character has to jump.")
			elseif destResult.Position.Y  - torsoPos.Y > 10 then
				print("Destination is out of vertical reach, finding new path.")
				path()
			end

			local destination = Vector3.new(rayOrigin.X, destResult.Position.Y, rayOrigin.Z)
					
			char.Humanoid:MoveTo(destination)
					
			char.Humanoid.MoveToFinished:Wait()
			print(Vector3.new(math.round(char.Torso.Position.X),math.round(char.Torso.Position.Y),math.round(char.Torso.Position.Z)))		
			print(Vector3.new(math.round(destination.X),math.round(destination.Y),math.round(destination.Z)))
					
			part(destResult.Position, Color3.fromRGB(255,0,0))
					
			debounce = false

		else

			print("Finding new path...")
			debounce = false
			path()

		end

	else
		print(char.Name .. " is stuck - path not created.")
		if stuck.Value == false then
			stuck.Value = true
		end
	end
end

For clarity:
RollX() and rollZ() are just separate math.random(-30,30) functions that decide where the character should move. The Stuck value is not being changed in the script yet, but it will be used for detecting if the character really can’t find any destination point. Although it would be a rare occasion, I will later make it so it takes three tries to find a path, and if none succeed, Stuck will be true. If true, the character will purely pick a completely random destination point (without raycasting) and repeatedly jump.

After the character finishes walking, I print the position of the character and the destination point’s position, and it seems to be roughly correct (in the video the printed Y values aren’t consistent, but this has been fixed and it’s ireelevant). There is a very insignificant deviation between X and Z, suggesting everything is correct, compared to the deviation seen with the debug bricks. However, I don’t know why the brick spawns somewhere else, and this becomes super enigmatic, as the destination point could be higher, but reachable by the character if I make them jump, however in such a case it is not clear if the character should jump, because the destination point could be somewhere else.

I bet this is a really small mistake and I’m not attentive enough to spot it…

What I also noticed is that the debug brick tends to consistently be offset 8 studs to one side and 7 to the other. This is also seen in the video lol, I genuinely don’t know what is this

I would suggest using the Roblox pathfinding system, because trying to make your own is difficult, and raycasting repeatedly reduces the performance of the game.

How can I help you with your problem?

Making a Proper Pathfinding System with PathfinidngService is also difficult, plus you would be better off making your own if you want more stuff to it.

1 Like

It depend on what your using the pathfinding system for. Example: A monster ai.

Some AI doesnt use PathfindingService, They use a Custom Pathfinding system.

I previously used PathfindingService (I did implictly state this in the original post), but it was incredibly inconsistent as sometimes when the server had started, even after putting a delay for when the NPC spawns, the path script yielded Enum.PathStatus.NoPath. At other times it was perfectly fine. I had even less clue what was wrong. It might had something to do with server lag, as multiple NPCs could consecutively spawn, but I’m just speculating at this point

1 Like

There could be multiple reasons why this went wrong. There could have been something blocking the path or you could have set the agent parameters too high or the can jump parameter to false. Examples: Height, Radius, Can Jump.

Thats what I mean by its difficult to make a Proper Pathfinding System with PathfindingService

Also, can you show a Video of the Issue?

1 Like

You should check out these videos on pathfinding: AI Monster Pathfinding -Teddy Horror Game #2 - YouTube

Here is the previous iteration of the path function, using PathfindingService, for your convenience. I can assure you it was flawless in pure function, but in practice it was unpredictable.

local function path()

	if stuck.Value == false and debounce == false then

		debounce = true

		local path = pfService:CreatePath({
			WaypointSpacing = math.huge
				})

		local destination = Vector3.new(char.Torso.Position.X + rollX(), char.Torso.Position.Y, char.Torso.Position.Z + rollZ())	

		path:ComputeAsync(char.Torso.Position, destination)

		print("Path status: " .. tostring(path.Status))
		print("Generated " .. #waypoints .. " waypoints.")

		if stuck.Value == false then
			if path.Status == Enum.PathStatus.NoPath then
				stuck.Value = true
			else
				local waypoints = path:GetWaypoints()
				for i, v in pairs(waypoints) do
					if v.Action == Enum.PathWaypointAction.Jump then
						char.Humanoid.Jump = true
					end
					char.Humanoid:MoveTo(v.Position)
					char.Humanoid.MoveToFinished:Wait()
					if i == #waypoints then
						debounce = false
					end
				end
			end
		end

	else
		print(char.Name .. " is stuck - path not created.")
	end

end

Why did you set the waypoint spacing to math.huge? That’s a really massive number. Also did you set the agent can jump to true?

Because there is no need for more inflection points if the Humanoid has to walk only to one point. This way, it creates inflection points only if the Pathfinding detects an obstacle. CanJump is unneccessary to set up, because I simply make the character jump if the inflection point action is Jump.

I’m will implement that code into my game and I will test it out. It functions fine for me.

local char = script.Parent
local debounce = false

local pfService = game:GetService(“PathfindingService”)

local stuck = char:WaitForChild(“Stuck”)

local function path()

if stuck.Value == false and debounce == false then

	debounce = true

	local path = pfService:CreatePath({
		WaypointSpacing = math.huge
	})

	local destination = Vector3.new(char.HumanoidRootPart.Position.X + math.random(-30, 30), char.HumanoidRootPart.Position.Y, char.HumanoidRootPart.Position.Z + math.random(-30, 30))	

	path:ComputeAsync(char.HumanoidRootPart.Position, destination)

	print("Path status: " .. tostring(path.Status))

	if stuck.Value == false then
		if path.Status == Enum.PathStatus.NoPath then
			stuck.Value = true
		else
			local waypoints = path:GetWaypoints()
			for i, v in pairs(waypoints) do
				if v.Action == Enum.PathWaypointAction.Jump then
					char.Humanoid.Jump = true
				end
				char.Humanoid:MoveTo(v.Position)
				char.Humanoid.MoveToFinished:Wait()
				if i == #waypoints then
					debounce = false
				end
			end
		end
	end

else
	print(char.Name .. " is stuck - path not created.")
end

end
while task.wait(5) do
path()
end

It’s very difficult to get it to happen, that’s what I meant by inconsistency. I swear there is like a 10% chance for Pathfinding to just not work in my game, just because.

I’m working on a monster game using pathfinding and it is working fine for me.

Nvm, finally got it on video. I checked if the game had rendered NavMeshes, and to nobody’s surprise, it appeared that it did not render them at all. I recorded another video of the pathfinding working perfectly fine on another instance, because NavMeshes were present. Hopefully this justifies the fact that I’m writing my own pathfinding script. Could we please focus on the main topic now?

Sorry for that. I will have to figure this out later. gtg.

Ok I think I should just be spawning the debug brick on “destination” instead of destResult.Position, and I think it’s because destResult.Position relies on the character’s torso position, which becomes different once the path is completed. My bet turned out to be true lololol