You can write your topic however you want, but you need to answer these questions:
What do you want to achieve? Keep it simple and clear!
I want to make Pathfinding AI, that has 2 Paths
What is the issue? Include screenshots / videos if possible!
You can see the issue on the video.
`
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried to do it with while loop cycle and it was working, but was really really slow.
---Services---
local PLS = game:GetService("Players")
local RS = game:GetService("RunService")
local PFS = game:GetService("PathfindingService")
local Debris = game:GetService("Debris")
---Variables---
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local RootPart = Character.HumanoidRootPart
local CanJump = false
local fov = 50;
local PathParams = {
AgentRadius = 6,
AgentHeight = 5,
AgentCanJump = CanJump,
}
RootPart:SetNetworkOwner(nil);
local WPs = workspace:FindFirstChild("Targets");
---Functions---
local function GetNearestPlayer()
local nearest = math.huge
local target = nil
for _, player in pairs(PLS:GetPlayers()) do
local character = player.Character
if character == nil then
continue
end
local distance = (character.HumanoidRootPart.Position - RootPart.Position)
if distance.Magnitude <= fov then
if distance.Magnitude < nearest then
nearest = distance.Magnitude
target = player
end
end
end
return target
end
local function getPath(destination)
local path: Path = PFS:CreatePath(PathParams);
path:ComputeAsync(RootPart.Position, destination);
return path;
end;
local function attack(target)
local tchar = target.Character;
if tchar then
local root = tchar:FindFirstChild("HumanoidRootPart");
if root then
local distance = (RootPart.Position - root.Position).Magnitude;
if distance > 8 then
local path = getPath(root.Position);
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints();
for index, waypoint in pairs(waypoints) do
Humanoid:MoveTo(waypoint.Position);
Humanoid.MoveToFinished:Wait();
end;
end;
else
local hum = tchar:FindFirstChild("Humanoid");
if hum then
hum.Health = 0;
end;
end;
end;
end;
end;
local function walkTo(destination)
local path = getPath(destination.Position);
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints();
for index, waypoint in pairs(waypoints) do
local target = GetNearestPlayer()
if target then
attack(target);
break;
else
Humanoid:MoveTo(waypoint.Position);
Humanoid.MoveToFinished:Wait();
end;
end;
end;
end;
local function patrol()
local waypoints = WPs:GetChildren();
local rand = math.random(1, #waypoints);
walkTo(waypoints[rand]);
end;
RS.Heartbeat:Connect(function()
patrol();
end);
--[[while wait(0.01) do
patrol()
end;]]
thanks for letting me know about that ModuleScript, but now i have other issue
When AI reaches the player it stops moving and dont do anything (you can see that in a video)
---Services---
local PLS = game:GetService("Players")
local RS = game:GetService("RunService")
local PFS = game:GetService("PathfindingService")
local SS = game:GetService("ServerStorage");
local Debris = game:GetService("Debris")
---Variables---
local Freddy = script.Parent
local Humanoid = Freddy:WaitForChild("Humanoid")
local RootPart = Freddy.HumanoidRootPart
local SimplePath = require(SS.SimplePath);
local MovingTo = nil;
local PreviousPath = nil;
local CanJump = false
local fov = 50;
local PathParams = {
AgentRadius = 6,
AgentHeight = 5,
AgentCanJump = CanJump,
}
RootPart:SetNetworkOwner(nil);
local WPs = workspace:FindFirstChild("Targets");
---Functions---
local function GetNearestPlayer()
local nearest = math.huge
local target = nil
for _, player in pairs(PLS:GetPlayers()) do
local character = player.Character
if character == nil then
continue
end
local distance = (character.HumanoidRootPart.Position - RootPart.Position)
if distance.Magnitude <= fov then
if distance.Magnitude < nearest then
nearest = distance.Magnitude
target = player
end
end
end
return target
end;
local function createFunc(path, argument)
path.Blocked:Connect(function()
path:Run(argument);
end);
path.Error:Connect(function()
path:Run(argument);
end);
path.WaypointReached:Connect(function()
local Target = GetNearestPlayer();
if not Target then
path:Run(argument);
else
local char = Target.Character;
if char then
local root = char:FindFirstChild("HumanoidRootPart");
if root then
path:Run(root);
end;
end
end;
end);
path.Reached:Connect(function()
if argument.Parent == WPs then
MovingTo = nil;
PreviousPath = argument;
end;
end);
end;
local function attack(target)
local tchar = target.Character;
if tchar then
local root = tchar:FindFirstChild("HumanoidRootPart");
if root then
local distance = (RootPart.Position - root.Position).Magnitude;
if distance > 8 then
local path = SimplePath.new(Freddy);
path.Visualize = true;
path:Run(root);
createFunc(path, root);
else
local hum = tchar:FindFirstChild("Humanoid");
if hum then
hum.Health = 0;
end;
end;
end;
end;
end;
local function walkTo(destination)
local path = SimplePath.new(Freddy);
local target = GetNearestPlayer();
if target then
attack(target);
else
path:Run(destination)
path.Visualize = true;
path:Run(destination);
createFunc(path, destination);
end
end;
local function patrol()
if not MovingTo then
local waypoints = WPs:GetChildren();
local rand;
repeat
rand = math.random(1, #waypoints);
until rand ~= PreviousPath;
MovingTo = waypoints[rand];
walkTo(waypoints[rand]);
end;
end;
RS.Heartbeat:Connect(function()
patrol();
end);
I figured it would be more interesting for you to try and debug the problem yourself. that came off as threatening didnnit?
Here’s an idea: using print in order to verify if everything is going as planned, i.e., “print debugging”.
You should try using print to verify the correctness of data (basically testing the code), so place it wherever the bug is more likely to be at, or wherever you feel like it.
For example, it could be that the if statement in the patrol function is failing because MovingTo has been set, but for whatever reason not reset. This “reason” is what we’re trying to find. It will be crucial in the debugging process.
Speaking of which, there is only one place where MovingTo is reset: in the callback of the path.Reached connection. In that same function, you check if argument (a HumanoidRootPart) is parented to WPs. And, if so, MovingTo is reset. Here’s the thing: what if it isn’t parented to WPs? Or even better: why would a player’s body part be parented to a instance other than the character, at all?
I wasn’t even trying to, but it appears I’ve found the issue. How would I solve this otherwise? Printing MoveTo, which would instantly signal the root of the problem.
Give a man a fish, and you feed him for a day; teach a man to fish, and you feed him for a lifetime Sun Tzu - Art Of War
HumanoidRootPart cant be paranted to WPs, WPs is just a Waypoints Folder in Workspace. Nextbot will be moving to one of children of that Folder, if he don’t see nearest player around him. I was printing out MovingTo and it was giving me one of parts located in WPs. And attack function now looks like this and still has the same issue
local function attack(target)
local tchar = target.Character;
if tchar then
local root = tchar:FindFirstChild("HumanoidRootPart");
if root then
local distance = (RootPart.Position - root.Position).Magnitude;
if distance > 8 then
local Path = SimplePath.new(Freddy);
Path.Visualize = true;
Path:Run(root);
Path.Blocked:Connect(function()
Path:Run(root);
end);
Path.Error:Connect(function()
Path:Run(root);
end);
else
print("killed that noob");
print(MovingTo, PreviousPath);
local hum = tchar:FindFirstChild("Humanoid");
if hum then
hum.Health = 0;
end;
end;
end;
end;
end;
i tried this and that works the same as RunService…
and i made my Freddy so it won’t kill my Player and for some reasons script won’t stop as soon as Freddy reaches the player…
I’m assuming that’s the problem of SimpePath probably or maybe there’s other ways out
Only take out the --Humanoid.MoveToFinished:Wait() in the attack function.
---Services---
local PLS = game:GetService("Players")
local RS = game:GetService("RunService")
local PFS = game:GetService("PathfindingService")
local Debris = game:GetService("Debris")
---Variables---
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local RootPart = Character.HumanoidRootPart
local CanJump = false
local fov = 50
local PathParams = {
AgentRadius = 6,
AgentHeight = 5,
AgentCanJump = CanJump,
}
RootPart:SetNetworkOwner(nil)
local WPs = workspace:FindFirstChild("Targets")
---Functions---
local function GetNearestPlayer()
local nearest = math.huge
local target = nil
for _, player in pairs(PLS:GetPlayers()) do
local character = player.Character
if character == nil then
continue
end
local distance = (character.HumanoidRootPart.Position - RootPart.Position)
if distance.Magnitude <= fov then
if distance.Magnitude < nearest then
nearest = distance.Magnitude
target = player
end
end
end
return target
end
local function getPath(destination)
local path: Path = PFS:CreatePath(PathParams)
path:ComputeAsync(RootPart.Position, destination)
return path
end
local function attack(target)
local tchar = target.Character
if tchar then
local root = tchar:FindFirstChild("HumanoidRootPart")
if root then
local distance = (RootPart.Position - root.Position).Magnitude
if distance > 8 then
local path = getPath(root.Position)
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for index, waypoint in pairs(waypoints) do
Humanoid:MoveTo(waypoint.Position)
--Humanoid.MoveToFinished:Wait()
end
end
else
local hum = tchar:FindFirstChild("Humanoid")
if hum then
hum.Health = 0
end
end
end
end
end
local function walkTo(destination)
local path = getPath(destination.Position)
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for index, waypoint in pairs(waypoints) do
local target = GetNearestPlayer()
if target then
attack(target)
break
else
Humanoid:MoveTo(waypoint.Position)
Humanoid.MoveToFinished:Wait()
end
end
end
end
local function patrol()
local waypoints = WPs:GetChildren()
local rand = math.random(1, #waypoints)
walkTo(waypoints[rand])
end
--RS.Heartbeat:Connect(function()
-- patrol()
--end)
while wait(0.01) do
patrol()
end
so i tried to make one that i think does what we want. See if you can make it work for your AI.
local Debris = game:GetService("Debris")
local PathFindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local Character = script.Parent
local root = Character.HumanoidRootPart
local FOV = 50
local function points(pos, color)
local point = Instance.new("Part")
point.Position = pos
point.Color = color
point.Size = Vector3. new(.3,.3,.3)
point.Anchored = true
point.CanCollide = false
point.Parent = workspace
Debris:AddItem(point,4)
end
local function Target()
local closestHumanoid = nil
local distance = FOV
for i, v in Players:GetChildren() do
if (v.Character.PrimaryPart.Position - Character.PrimaryPart.Position).Magnitude < distance then
distance = (v.Character.PrimaryPart.Position - Character.PrimaryPart.Position).Magnitude
closestHumanoid = v.Character
end
end
if closestHumanoid == nil then
local random = math.random(-FOV,FOV)
local position = root.CFrame * CFrame.new(random,0,random)
return position.Position,true
else
local playerVelocity = closestHumanoid.Humanoid.MoveDirection * closestHumanoid.Humanoid.WalkSpeed
local futurePosition = closestHumanoid.PrimaryPart.Position + playerVelocity * 1
return futurePosition,false
end
end
local function followPath(target)
local targetDistance = (target - Character.PrimaryPart.Position).magnitude
local dynamicSpacing = math.clamp(targetDistance / 2.75, 1, 15)
print(dynamicSpacing)
local path1 = PathFindingService:CreatePath({
AgentCanJump = true,
AgentCanClimb = true,
WaypointSpacing = dynamicSpacing,--
AgentRadius = 3,
AgentHight = 8,
Costs = {
DangerZone = math.huge
}
})
local path2 = PathFindingService:CreatePath({
AgentCanJump = true,
AgentCanClimb = true,
WaypointSpacing = dynamicSpacing / 10,--
AgentRadius = 3,
AgentHight = 8,
Costs = {
DangerZone = math.huge
}
})
path1:ComputeAsync(Character.PrimaryPart.Position, target)
local waypoints1 = path1:GetWaypoints()
for i = 1,3 do
if waypoints1[i] == nil or waypoints1[i+1] == nil then
else
points(waypoints1[i].Position, Color3.fromRGB(43, 0, 255))
path2:ComputeAsync(Character.PrimaryPart.Position, waypoints1[i+1].Position)
local waypoints2 = path2:GetWaypoints()
for _, waypoint2 in waypoints2 do
points(waypoint2.Position, Color3.fromRGB(9, 255, 5))
if waypoint2.Action == Enum.PathWaypointAction.Jump then
print("JUMP")
Character.Humanoid.Jump = true
end
Character.Humanoid:MoveTo(waypoint2.Position)
end
end
end
end
repeat
local target,patrol = Target()
if patrol == true then
followPath(target)
Character.Humanoid.MoveToFinished:Wait()
else
task.spawn(followPath,target)
end
task.wait(.25)
until nil