Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

How would I go about making an AI that chases and kills you around obstacles?

I am making a game that is very similar to [The Rake] (https://www.roblox.com/games/2413927524/THE-RAKE-Classic-Edition-v1-1-1c)

You're put in a map that has buildings and other obstacles littered around it. There is a monster that is supposed to chase you throughout this map. I have used basic things like MoveTo(), but obviously that doesn't work very well because the monster can't get around obstacles. So I tried different ways to do this using pathfinding, but I still can't get it just right.

This is my code as of right now. If it looks cluttered it's because I've constantly been changing it to try to fit my needs.

local runSpeed = 28
local pathService = game:GetService("PathfindingService")
local humanoid = script.Parent.Humanoid

humanoid.WalkSpeed = runSpeed

function findNearestTorso(pos)
	local list = game.Workspace:children()
	local torso = nil
	local dist = 800
	local temp = nil
	local human = nil
	local temp2 = nil
	for x = 1, #list do
		temp2 = list[x]
		if (temp2.className == "Model") and (temp2 ~= script.Parent) then
			temp = temp2:findFirstChild("HumanoidRootPart")
			human = temp2:findFirstChild("Humanoid")
			if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
				if (temp.Position - pos).magnitude < dist then
					torso = temp
					dist = (temp.Position - pos).magnitude
				end
			end
		end
	end
	return torso
end

local path

while true do
	wait(0.5)
	local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
		path = pathService:CreatePath()
		path:ComputeAsync(script.Parent.HumanoidRootPart.Position, target.Position)
		
		local waypoints = path:GetWaypoints()
		
		if path.Status == Enum.PathStatus.Success then
			for i,v in pairs(waypoints) do
				local part = Instance.new("Part", workspace)
				part.Anchored = true
				part.CanCollide = false
				part.Material = Enum.Material.Neon
				part.Position = v.Position
				part.Size = Vector3.new(0.6,0.6,0.6)
				part.Shape = "Ball"
				
				humanoid:MoveTo(v.Position)
				
				if v.Action == Enum.PathWaypointAction.Jump then
					humanoid.Jump = true
				end	
			end
		end
	end
end

Like I said it's pretty cluttered. What this does right now is it makes a path over and over towards the closest player. But instead of following this path correctly, the monster goes straight to the waypoint at the end of the path. Also, the monster is supposed to jump over obstacles in the path, but fails to do so. I've been at this all day and haven't been able to come to a solution. Keep in mind most of this is bits and pieces from videos, forums, the wiki etc. I am not an experienced scripter so most of this is pretty difficult for me.

Please, if you can, explain and show me how to fix this and how to do it efficiently, if possible. Thanks.

3 comments

0

ALSO MAKE A VALUE

0

there are alot of pathfinding models, i would just use the scripts in those

0

I did try that but none of them really worked well

2 answers

✓ Accepted answer

if you want path finding, do this and put a value and name it Target

debugMode = false
targetNPCs = false

--

h = script.Parent.Parent:WaitForChild("Humanoid")
pathService = game:GetService("PathfindingService")
targetV = script.Parent:WaitForChild("Target")

function closestTargetAndPath()
	local humanoids = {}
	if targetNPCs then
		local function recurse(o)
			for _,obj in pairs(o:GetChildren()) do
				if obj:IsA("Model") then
					if obj:findFirstChild("Humanoid") and obj:findFirstChild("Torso") and obj.Humanoid ~= h and obj.Humanoid.Health > 0 and not obj:findFirstChild("ForceField") then
						table.insert(humanoids,obj.Humanoid)
					end
				end
				recurse(obj)
			end
		end
		recurse(workspace)
	else
		for _,v in pairs(game.Players:GetPlayers()) do
			if v.Character and v.Character:findFirstChild("HumanoidRootPart") and v.Character:findFirstChild("Humanoid") and v.Character.Humanoid.Health > 0 and not v:findFirstChild("ForceField") then
				table.insert(humanoids,v.Character.Humanoid)
			end
		end
	end
	local closest,path,dist
	for _,humanoid in pairs(humanoids) do
		local myPath = pathService:ComputeRawPathAsync(h.Torso.Position,humanoid.Torso.Position,500)
		if myPath.Status ~= Enum.PathStatus.FailFinishNotEmpty then
			-- Now that we have a successful path, we need to figure out how far we need to actually travel to reach this point.
			local myDist = 0
			local previous = h.Torso.Position
			for _,point in pairs(myPath:GetPointCoordinates()) do
				myDist = myDist + (point-previous).magnitude
				previous = point
			end
			if not dist or myDist < dist then -- if true, this is the closest path so far.
				closest = humanoid
				path = myPath
				dist = myDist
			end
		end
	end
	return closest,path
end

function goToPos(loc)
	h:MoveTo(loc)
	local distance = (loc-h.Torso.Position).magnitude
	local start = tick()
	while distance > 4 do
		if tick()-start > distance/h.WalkSpeed then -- Something may have gone wrong. Just break.
			break
		end
		distance = (loc-h.Torso.Position).magnitude
		wait()
	end
end

while wait() do
	local target,path = closestTargetAndPath()
	local didBreak = false
	local targetStart
	if target and h.Torso then
		targetV.Value = target
		targetStart = target.Torso.Position
		roaming = false
		local previous = h.Torso.Position
		local points = path:GetPointCoordinates()
		local s = #points > 1 and 2 or 1
		for i = s,#points do
			local point = points[i]
			if didBreak then 
				break
			end
			if target and target.Torso and target.Health > 0 then
				if (target.Torso.Position-targetStart).magnitude < 1.5 then
					local pos = previous:lerp(point,.5)
					local moveDir = ((pos - h.Torso.Position).unit * 2)
					goToPos(previous:lerp(point,.5))
					previous = point
				end
			else
				didBreak = true
				break
			end
		end
	else
		targetV.Value = nil
	end
	if not didBreak and targetStart then
		goToPos(targetStart)
	end
end

1 comment

0

I'm pretty happy with the final product. The only thing that seems to still not be working is when the monster gets close to you, it kind of glitches out and can't touch you while your walking. If you could help me out with that problem then it'll be perfect! Thanks a ton!

i have fixed your code it may be a bit laggy

local runSpeed = 28
local pathService = game:GetService("PathfindingService")
local humanoid = script.Parent.Humanoid
humanoid.Parent.PrimaryPart:SetNetworkOwner(nil)

humanoid.WalkSpeed = runSpeed

function findNearestTorso(pos)
	local list = game.Workspace:children()
	local torso = nil
	local dist = 800
	local temp = nil
	local human = nil
	local temp2 = nil
	for x = 1, #list do
		temp2 = list[x]
		if (temp2.className == "Model") and (temp2 ~= script.Parent) then
			temp = temp2:findFirstChild("HumanoidRootPart")
			human = temp2:findFirstChild("Humanoid")
			if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
				if (temp.Position - pos).magnitude < dist then
					torso = temp
					dist = (temp.Position - pos).magnitude
				end
			end
		end
	end
	return torso
end

local path

while true do
	wait(0.5)
	local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
		path = pathService:CreatePath()
		path:ComputeAsync(script.Parent.HumanoidRootPart.Position, target.Position)

		local waypoints = path:GetWaypoints()

		if path.Status == Enum.PathStatus.Success then
			for i,v in pairs(waypoints) do
				local part = Instance.new("Part", workspace)
				part.Anchored = true
				part.CanCollide = false
				part.Material = Enum.Material.Neon
				part.Position = v.Position
				part.Size = Vector3.new(0.6,0.6,0.6)
				part.Shape = "Ball"



				if v.Action == Enum.PathWaypointAction.Jump then
					humanoid.Jump = true
				end 
				humanoid:MoveTo(v.Position)
				humanoid.MoveToFinished:Wait()
			end
		end
	end
end

hope you like it

This discussion is preserved as it was. New answers, comments, and votes are closed.