NPC Movement Query

I have attempted to try and create path finding without using a while loop. I’ve created two types. My first prototype is a mix of Path finding, MoveTo() and Raycast checks to see if it can reach the player without needing to jump or do something which moveto cant do. Now the issue with this is obviously that HRP to HRP can cause issues with a check since the player may be slightly higher but their HRP is perfectly exposed with nothing in the way. So then I tried doing purely path finding which is less consistent at turning and being reactive. Is there anyway to have smooth reaction from a NPC with pathfinding without the need of constant looping at a extreme rate?

The Second prototype code (PathFinding only)

function followPath(npc,destinationObject,humanoid)
	-- Compute and check the path
	NPCS[npc]["Path"]:ComputeAsync(npc.HumanoidRootPart.Position, destinationObject.HumanoidRootPart.Position)
	NPCS[npc]["Waypoints"] = {}

	if NPCS[npc]["Path"].Status == Enum.PathStatus.Success then
		NPCS[npc]["Waypoints"] = NPCS[npc]["Path"]:GetWaypoints()
		NPCS[npc]["WaypointIndex"] = 1
		humanoid:MoveTo(NPCS[npc]["Waypoints"][NPCS[npc]["WaypointIndex"]].Position)
		setNetworkOwner(npc)
	else
		warn("Path errored")
		npcFunctionality(npc)
	end
end

local defaultDistance = 10
local closeRangeDistance = 5

function onWaypointReached(reached,npc)

	local _,r = pcall(function()
		if reached and NPCS[npc]["WaypointIndex"] < #NPCS[npc]["Waypoints"] then
			warn(NPCS[npc]["Waypoints"][1].Position)
			warn(NPCS[npc]["Waypoints"][NPCS[npc]["WaypointIndex"]].Position)
			warn(NPCS[npc]["Waypoints"][NPCS[npc]["WaypointIndex"]].Action)
			if NPCS[npc]["Waypoints"].Action == Enum.PathWaypointAction.Jump then --detects whether or not it has to jump
				npc.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping) --jump
			end
			
			if (NPCS[npc]["Waypoints"][1].Position - NPCS[npc]["Waypoints"][NPCS[npc]["WaypointIndex"]].Position).magnitude > defaultDistance then
				-- "has exceeded a distance threshold"
				warn("has exceeded distance req, create a new path")
				npcFunctionality(npc)
			elseif (npc.HumanoidRootPart.Position - NPCS[npc]["Target"].HumanoidRootPart.Position).Magnitude < closeRangeDistance then
				warn("Npc is very close, re-adjust path")
				followPath(npc,NPCS[npc]["Target"],npc.Humanoid)
			else
				NPCS[npc]["WaypointIndex"] += 1
				npc.Humanoid:MoveTo(NPCS[npc]["Waypoints"][NPCS[npc]["WaypointIndex"]].Position)
			end
		else
			npcFunctionality(npc)
		end
	end)


	if r then
		warn(r)
		npcFunctionality(npc)
	end
end

function onPathBlocked(blockedWaypointIndex,npc)
	if blockedWaypointIndex > NPCS[npc]["WaypointIndex"] then
		npcFunctionality(npc)
	end
end

npcFunctionality = function(npc)
	local hrp = npc.HumanoidRootPart
	local humanoid = npc.Humanoid
	local Subject,Action = findNearestHuman(npc)
	warn(Action)
	NPCS[npc]["Action"] = Action
	if Action == "ComputePathway" then
		followPath(npc,Subject,humanoid)
	elseif Action == "NoAction" then
		npc.Humanoid:MoveTo(Vector3.new(hrp.Position.X + math.random(10,20),hrp.Position.Y,hrp.Position.Z + math.random(10,20)))
		setNetworkOwner(npc)
	end	
end

I’m ideally looking to have around 40-50 NPCS spawned at once with at least only 10-15 frames being devoured to be able to handle calculating for them. Any Ideas?

3 Likes