Currently trying to figure out why this NPC follows me as it should for a few seconds, then it randomly enters its Pathfinding phase.
https://puu.sh/IKais/a1327a8259.mp4
The NPC will approach the player if they are within 24 studs, then it starts to follow them, but on top of that, it also fires a raycast every second, to check for obstructions (this means two loops at the same time, also not sure if I’m doing this in the right way, so please let me know xd).
The problem happens here, as it finds obstructions that are not even there. The script goes as follows:
local function scan(currentTarget)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {
game.Players:FindFirstChild(currentTarget).Character,
char
}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local result = workspace:Raycast(char.Torso.Position, game.Players:FindFirstChild(target.Value).Character.Torso.Position, raycastParams)
local p1 = Instance.new("Part")
p1.Position = char.Torso.Position
p1.Shape = "Ball"
p1.Anchored = true
p1.CanCollide = false
p1.CanTouch = false
p1.CanQuery = false
p1.Size = Vector3.new(1,1,1)
p1.BrickColor = BrickColor.new("New Yeller")
local p2 = Instance.new("Part")
p2.Position = game.Players:FindFirstChild(target.Value).Character.Torso.Position
p2.Shape = "Ball"
p2.Anchored = true
p2.CanCollide = false
p2.CanTouch = false
p2.CanQuery = false
p2.Size = Vector3.new(1,1,1)
p2.BrickColor = BrickColor.new("New Yeller")
local distance = (char.Torso.Position - game.Players:FindFirstChild(currentTarget).Character.Torso.Position).Magnitude
local p = Instance.new("Part")
p.Anchored = true
p.CanTouch = false
p.CanCollide = false
p.CanQuery = false
p.Size = Vector3.new(0.5, 0.5, distance)
p.BrickColor = BrickColor.new("New Yeller")
p.CFrame = CFrame.lookAt(char.Torso.Position, game.Players:FindFirstChild(target.Value).Character.Torso.Position)*CFrame.new(0, 0, -distance/2)
wait()
p.Parent = workspace
p1.Parent = workspace
p2.Parent = workspace
if result then
print("Found obstruction!")
stuck.Value = true
end
wait(1)
p:Destroy()
p1:Destroy()
p2:Destroy()
end
local function chase()
local currentTarget = target.Value
print(currentTarget)
coroutine.resume(coroutine.create(function()
while target.Value == currentTarget and stuck.Value == false do
wait()
char.Humanoid:MoveTo(game.Players:FindFirstChild(currentTarget).Character.Torso.Position)
local distance = (char.Torso.Position - game.Players:FindFirstChild(target.Value).Character.Torso.Position).Magnitude
if distance > minimumDistance * 2 then
target.Value = ""
end
end
end))
while target.Value == currentTarget and stuck.Value == false do
scan(target.Value)
--wait(1)
end
end
local function find()
print("Spawning part")
local offset = Vector3.new(0,0,12)
local temp = Instance.new("Part")
temp.Transparency = 1
temp.Anchored = true
temp.Position = char.Torso.Position
temp.CFrame = char.Torso.CFrame*CFrame.new(offset)
temp.CanCollide = false
temp.CanTouch = false
temp.CanQuery = false
temp.Parent = workspace
wait()
char.Humanoid:MoveTo(temp.Position)
temp:Destroy()
wait(0.2)
local toChase = game.Players:FindFirstChild(target.Value).Character
print("Attempting to chase player: " .. toChase.Name)
local path = pfService:CreatePath({
WaypointSpacing = math.huge -- maybe with each inflection point fire moar raycasts
-- this way you can check if pathfinding state is worth still running
})
path:ComputeAsync(char.Torso.Position, toChase.Torso.Position)
local waypoints = path:GetWaypoints()
print("Path status: " .. tostring(path.Status))
print("Generated " .. #waypoints .. " waypoints.")
for i, v in pairs(waypoints) do
if v.Action == Enum.PathWaypointAction.Jump then
if jumped == false then
char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
else
repeat wait() until jumped == false
char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
char.Humanoid:MoveTo(v.Position)
char.Humanoid.MoveToFinished:Wait(2)
if i == #waypoints then
print("Target reached.")
stuck.Value = false
end
end
end
These functions are called based on the signal that I’m very primitively using in order to detect any changes (plz no judging, if there’s a better way of doing this tell me!!):
signal.Changed:Connect(function()
if signal.Value == true then
print("Received ping!")
if stuck.Value == false and target.Value == "" then
print("Idling...")
idle()
elseif stuck.Value == false and target.Value ~= "" then
if behavior.Value == "Hostile" or behavior.Value == "Neutral" then
print("Chasing...")
chase()
elseif behavior.Value == "Friendly" or behavior.Value == "Asocial" then
print("Fleeing...")
flee()
end
elseif stuck.Value == true and target.Value ~= "" then
print("Finding...")
find()
end
end
end)
I have tried pretty much anything I could think of, I tried blacklisting the character and the chased character, visualizing the raycast (even disabling CanQuery too), spamming waits everywhere, even casually rewriting this script for the third time. If there is something I missed, please let me know!!