I’ve been at this for a while now, but have found no methods that work.
The problem right now is that if I just use MoveTo() it goes to the position the object is at, but it doesnt account for the fact that the object can move.
Once the object has moved, it doesnt matter cause the NPC just walks to the position the Object was at when the MoveTo() Started.
Ive read countless posts, none of them seemed to tackle this challenge.
The current idea I have is that I would just tell when the object moves, and then stop the MoveTo (ps how do I stop the MoveTo??)
but I wasnt sure how optimized that’d be.
Also if anyone wants to help, any ideas to optimize this code?
function Class:EnableAI(Model:Model)
local Humanoid = Model:FindFirstChildWhichIsA('Humanoid', true)
repeat
-- // Locate Target //
local Target = Pathfinding:FindNearestPlayer(Model.PrimaryPart.Position); if not Target then continue end
local TargetRoot = Target.Character.PrimaryPart
local Complete = false
-- // If Target, Follow it //
if Target then
-- // Pathfind //
-- || PS this function just fires a Raycast to the Target.Character ||
if Pathfinding:ObjectInSight(Model.PrimaryPart.Position, Target.Character, workspace.Enemies:GetDescendants()) then -- // Walk Directly towards Target //
-- // I need to change this code to follow the TargetRoot //
repeat
Humanoid:MoveTo(TargetRoot.Position)
task.wait()
until ((TargetRoot.Position - Model.PrimaryPart.Position).Magnitude < 2) or not Pathfinding:ObjectInSight(Model.PrimaryPart.Position, Target.Character, workspace.Enemies:GetDescendants())
Complete = true
else
-- // This is Pathfinding stuff //
local Path = Pathfinding:FollowPath(Model, Model.PrimaryPart.Position, TargetRoot.Position, true)
if Path then
Path.Complete:Once(function()
Complete = true
end)
Path.Failed:Once(function(Quit)
if Quit then
warn('No Longer following Path.')
Complete = true
end
end)
end
end
else
warn('No Target')
Complete = true
end
repeat task.wait() until Complete
task.wait(0.4)
until Humanoid.Health <= 0
end
local RunService = game:GetService("RunService")
function Class:EnableAI(Model: Model)
local Humanoid = Model:FindFirstChildWhichIsA('Humanoid', true)
if not Humanoid or not Model.PrimaryPart then
warn("No humanoid or primary part found!")
return
end
local function FollowTarget(TargetRoot)
local updateConnection
updateConnection = RunService.Heartbeat:Connect(function()
if not TargetRoot or not TargetRoot.Parent or Humanoid.Health <= 0 then
updateConnection:Disconnect()
return
end
-- Move directly if in sight, otherwise use pathfinding
if Pathfinding:ObjectInSight(Model.PrimaryPart.Position, TargetRoot.Parent, workspace.Enemies:GetDescendants()) then
Humanoid:MoveTo(TargetRoot.Position)
else
local Path = Pathfinding:FollowPath(Model, Model.PrimaryPart.Position, TargetRoot.Position, true)
if Path then
Path.Complete:Once(function()
-- Path completed, continue updating
end)
Path.Failed:Once(function(Quit)
if Quit then
warn('Pathfinding failed.')
end
end)
end
end
end)
end
while Humanoid.Health > 0 do
local Target = Pathfinding:FindNearestPlayer(Model.PrimaryPart.Position)
if Target and Target.Character and Target.Character.PrimaryPart then
FollowTarget(Target.Character.PrimaryPart)
end
task.wait(0.4) -- Prevent CPU overload
end
end
Ok so, Im not exactly sure why, but for whatever reason after like 5 or 7 seconds the enemy starts pathfinding when Im in front of it I think, but it keeps going like back and fourth for some reason.
ignore the poor quality.
There are also no errors at all, there is something printing in the output which shows that the enemy is pathfinding, so I believe it has something to do with that
What happens when there is only one npc? Does your code ignore the other npc when it raycast or pathfinding? This is the only thing I see as a possible problem.
The raycasts I can confirm ignore the other NPC’s, all the NPC’s are also in a collision group that makes it so they ignore each other so that might mean that the pathfinding would ignore the other NPCs, but Im not sure.
I did also test this with just one npc but I think it yielded the same result
Sorry for the wait, I go some difficulty with obs, it this what your are trying to do? I don’t make it like your current code, but you can take inspiration i try to name thing the same
There are no comments, you can ask me if there’s something you don’t understand.
local RunService = game:GetService("RunService")
local SimplePath = require(script.SimplePath)
local Path
local Humanoid
local HumanoidRootPart
local Target
local ObjectInSight
local beam
local brickcolor = BrickColor.random()
local function DebugRaycast(Origin, Direction, Length, Result)
beam = beam or Instance.new("Part")
beam.Name = "DebugRaycast"
beam.Size = Vector3.new(0.2, 0.2, Length)
beam.CFrame = CFrame.lookAt(Origin.Position, Origin.Position + Direction) * CFrame.new(0, 0, -beam.Size.Z / 2)
beam.BrickColor = brickcolor
beam.Material = Enum.Material.Neon
beam.Anchored = true
beam.CanCollide = false
beam.CanQuery = false
beam.CanTouch = false
beam.Parent = workspace
--print(Result)
end
local function CheckObjectInSight(Model, Target, IgnoreList)
local ModelRoot = Model.PrimaryPart
local TargetRoot = Target.PrimaryPart
local Direction = (TargetRoot.Position - ModelRoot.Position)
IgnoreList = IgnoreList or {}
table.insert(IgnoreList, Model)
for Index, Object in pairs(Target:GetChildren()) do
if Object ~= TargetRoot then
table.insert(IgnoreList, Object)
end
end
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = IgnoreList
Params.FilterType = Enum.RaycastFilterType.Exclude
local Result = workspace:Raycast(ModelRoot.Position, Direction, Params)
DebugRaycast(ModelRoot, Direction, Result and Result.Distance or Direction.Magnitude, Result)
if Result and Result.Instance == TargetRoot then
return true
else
return false
end
end
local function FindNearestPlayer()
return workspace:FindFirstChild("Ehtrab")
end
local function CancelMove()
Humanoid:MoveTo(HumanoidRootPart.Position)
end
local function EnableAI(Model)
Humanoid = Model:FindFirstChildWhichIsA("Humanoid", true)
if not Humanoid then return end
HumanoidRootPart = Humanoid.RootPart
if not HumanoidRootPart then return end
while true do
local DeltaTime = RunService.Heartbeat:Wait()
Target = FindNearestPlayer()
if not Target then CancelMove() continue end
local TargetHumanoid = Target:FindFirstChildWhichIsA("Humanoid", true)
if not TargetHumanoid or TargetHumanoid.Health == 0 then CancelMove() continue end
local TargetRoot = Target.PrimaryPart
if not TargetRoot then CancelMove() continue end
ObjectInSight = CheckObjectInSight(Model, Target, workspace.Ignore:GetChildren())
if ObjectInSight then
Humanoid:MoveTo(TargetRoot.Position)
else
if not Path then
Path = SimplePath.new(Model)
Path.Visualize = true
end
Path:Run(TargetRoot)
end
end
end
EnableAI(script.Parent)
Thanks for the help! I took some inspiration from your code and I was able to get it in running order.
A big problem I noticed was for my ObjectInSight funtion it only checks if the raycast hit the HumanoidRootPart of the target, so I fixed that, and it started working a whole lot better!