I made this monster that goes to different waypoints and chases the player when it sees them. I’m having an issue where after it chases someone for the first time it gets a lot slower and kinda stutters whenever it chases someone again.
here’s the script, it’s really messy because i took parts of other scripts i found and put them together and it sorta works lol
local Pathfinding = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService("RunService")
local rig = script.Parent
local PathfindingService = game:GetService("PathfindingService")
local animations = script.Animations
local path = Pathfinding:CreatePath({
AgentHeight = 9;
AgentRadius = 3;
AgentCanJump = false;
Costs = {
Water = 100;
DangerZone = math.huge
}
})
local Character = script.Parent
local humanoid = Character:WaitForChild("Humanoid")
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function canSeePlayer()
for _, player in Players:GetPlayers() do
local playerCharacter = player.Character or player.CharacterAdded:Wait()
if playerCharacter and playerCharacter.PrimaryPart then
local playerPos = playerCharacter.PrimaryPart.Position
local monsterPos = rig.PrimaryPart.Position
local direction = (playerPos - monsterPos).unit * (playerPos - monsterPos).magnitude
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {rig}
local result = workspace:Raycast(monsterPos, direction, raycastParams)
if result and result.Instance:IsDescendantOf(playerCharacter) then
return true
end
end
end
return false
end
for i,v in pairs(script.Parent:GetDescendants()) do
if v:IsA("Part") or v:IsA("MeshPart") then
v:SetNetworkOwner(nil)
end
end
local function findTarget()
local maxDistance = 100
local nearestTarget
for index, player in pairs(Players:GetPlayers()) do
if player.Character then
local target = player.Character
local distance = (Character.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
if distance < maxDistance then
nearestTarget = target
maxDistance = distance
end
if distance < 5 then
nearestTarget.Humanoid:TakeDamage(25)
end
end
end
return nearestTarget
end
local function followPath(destination)
local success, errorMessage = pcall (function()
path:ComputeAsync(Character.PrimaryPart.Position, destination)
print("yh")
end)
if success and path.Status == Enum.PathStatus.Success then
waypoints = path:GetWaypoints()
blockedConnection = path.Blocked:Connect (function(blockedWayPointIndex)
if blockedWayPointIndex >= nextWaypointIndex then
blockedConnection:Disconnect()
followPath(destination)
end
end)
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
local function calculatePath(destination)
local agentParams = {
["AgentHeight"] = 9,
["AgentRadius"] = 4,
["AgentCanJump"] = false
}
local path = PathfindingService:CreatePath(agentParams)
path:ComputeAsync(rig.HumanoidRootPart.Position, destination)
return path
end
local function walkToDestination(destination)
local path = calculatePath(destination)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in pairs(path:GetWaypoints()) do
local nearestPlayer = findTarget()
if nearestPlayer then
local FOV = math.cos(math.rad(120)) -- Use degrees, coverts degrees to a number between -1 and 1 to use compare to the dot product. You could also just change this to a number between -1 and 1 instead like .5 which is 45 degrees
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
local character = player.Character or player.CharacterAdded:Wait() -- or just use "continue" to skip if their character hasn't been loaded if you don't want to yield the thread
local direction = (character.HumanoidRootPart.Position - rig.Head.Position).Unit -- Get the direction from the Enemy to the Player
local lookVector = rig.Head.CFrame.LookVector
local dot = lookVector:Dot(direction) -- this is the dot product I mentioned.
if dot > FOV then -- include all angles within a range to be in the enemies FOV
if canSeePlayer() then
break
else
rig.Humanoid:MoveTo(waypoint.Position)
rig.Humanoid.MoveToFinished:Wait()
end
else
rig.Humanoid:MoveTo(waypoint.Position)
rig.Humanoid.MoveToFinished:Wait()
end
end
else
rig.Humanoid:MoveTo(waypoint.Position)
rig.Humanoid.MoveToFinished:Wait()
end
end
else
rig.Humanoid:MoveTo(destination - (rig.HumanoidRootPart.CFrame.LookVector * 10))
end
end
local function patrol()
script.Parent.Humanoid.WalkSpeed = 8
local waypoints = workspace.Waypoints.Bacteria3:GetChildren()
local randomNumber = math.random(1, #waypoints)
walkToDestination(waypoints[randomNumber].Position)
end
while task.wait() do
local target = findTarget()
if target then
local FOV = math.cos(math.rad(120))
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
local character = player.Character or player.CharacterAdded:Wait()
local direction = (character.HumanoidRootPart.Position - rig.Head.Position).Unit
local lookVector = rig.Head.CFrame.LookVector
local dot = lookVector:Dot(direction)
if dot > FOV then
if canSeePlayer() then
script.Parent.Humanoid.WalkSpeed = 20
print(target.Name)
followPath(target.HumanoidRootPart.Position)
if canSeePlayer() == false then
local Timer = 4
local WaitTime = 0.1
while Timer > 0 do
if canSeePlayer() then
break
end
wait(WaitTime)
Timer -= WaitTime
followPath(target.HumanoidRootPart.Position)
end
end
else
patrol()
end
else
patrol()
end
end
else
patrol()
end
end