Edited because I fixed some issues and have better wording.
I have this character that chases and kills the player. However, it has choppy movement when chasing, so the player can easily outrun it. How do I fix it?
(Headphones warning)
I do NOT want the player to outrun this mob. If the player is found, they will be caught.
local char = script.Parent
local humanoid = char.Humanoid
char.PrimaryPart:SetNetworkOwner(nil)
local pathFinder = game:GetService("PathfindingService")
local destinations = workspace.WorkerNightDestinations:GetChildren()
local always = true
local walkinganimation = script:WaitForChild("Walking")
local WalkAnim = humanoid:LoadAnimation(walkinganimation)
local chasingplayer = false
local TS = game:GetService("TweenService")
local clicking = char.HumanoidRootPart.Sound
local scream = char.HumanoidRootPart.Scream
clicking:Play()
WalkAnim:Play()
local fadeout = TS:Create(scream, TweenInfo.new(1.0, Enum.EasingStyle.Linear), {Volume = 0})
local function findNearestPlayer()
local nearestPlayer = nil
local shortestDistance = 200
for _, thing in pairs(workspace:GetChildren()) do
if thing:IsA("Model") and thing ~= char and thing.IsPatient.Value == true and thing.Humanoid.Health ~= 0 and thing.BreakingRule.Value == true then
local hrp = thing.HumanoidRootPart
local distance = (char.HumanoidRootPart.Position - hrp.Position).Magnitude
if distance <= shortestDistance then
nearestPlayer = thing
shortestDistance = distance
end
end
end
return nearestPlayer
end
humanoid.Touched:Connect(function(part)
if part.Parent:FindFirstChild("Humanoid") and part.Parent.Name ~= "Worker" and part.Parent.IsPatient.Value == true then
part.Parent.Humanoid.Health = 0
end
end)
-- MAIN LOOP
while always do
--if chasingplayer == false then
-- WalkAnim:Stop()
--end
local target = findNearestPlayer()
if not target then
target = destinations[math.random(1, #destinations)]
end
--if chasingplayer == false then
-- WalkAnim:Play()
--end
local path = pathFinder:CreatePath()
if target:IsA("Model") and target.Humanoid.Health ~= 0 then
path:ComputeAsync(char.HumanoidRootPart.Position, target.HumanoidRootPart.Position)
if chasingplayer == false then
scream.Volume = 7.797
scream:Play()
end
chasingplayer = true
else
path:ComputeAsync(char.HumanoidRootPart.Position, target.Position)
if chasingplayer == true then
fadeout:Play()
chasingplayer = false
end
end
for _, wayPoint in pairs(path:GetWaypoints()) do
char.Humanoid:MoveTo(wayPoint.Position)
if wayPoint.Action == Enum.PathWaypointAction.Jump then
char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
char.Humanoid.MoveToFinished:Wait()
if target:IsA("Model") and target ~= char and target.IsPatient.Value == true and (char.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude <= 2 then
print("Player found.")
char.Humanoid:MoveTo(target.HumanoidRootPart.Position)
char.Humanoid.MoveToFinished:Wait()
chasingplayer = false
break
end
end
end
I’m new to coding, so sorry if my code makes no sense or is hard to read.
2 Likes
Bro i’m still having this issue, pls help
If you are truly new to coding, I am proud of you, because it’s a lot nicer than some of what I see on here. Anyway, I think the main issue you are having is complicated. path:ComputeAsync() takes time (emphasis on Async). Whenever the NPC is recalculating the path, it is staying still, allowing the character to get away, such that where it is calculating a path to is no longer relevant, AND it is staying still. Does this make sense?
You can get around this with a more complicated AI. Have multiple while loops, one of them always moving to waypoints, the other one deciding when to recalculate and reset the waypoints. You can use task.spawn() to run multiple while loops at once (in a general sense, they don’t actually run at the same time).
Though, an easier solution that might help is calculating to where the character will be. Perhaps by adding character.PrimaryPart.AssemblyLinearVelocity or maybe there is a more accurate property of Humanoid. You could also move to the next waypoint WHILE recalculating the path (move the MoveTo to be right before the break
. Things like this might help, but this is hard to solve.
I should’ve specified that I am new to complicated Roblox scripting, not coding in general, my mistake ^^’ I have been doing other types of coding for years, and I have worked on a Roblox game before (but nothing as complicated as this current project). (My script looks nice because it is a Frankenstein of other tutorials I’ve seen) But thanks anyway!!
I’ll try out your solutions and get back to you! thanks for helping out!
I’m gonna be real with you chief I have no idea what im doing
local char = script.Parent
local humanoid = char.Humanoid
char.PrimaryPart:SetNetworkOwner(nil)
local pathFinder = game:GetService("PathfindingService")
local destinations = workspace.WorkerNightDestinations:GetChildren()
local always = true
local walkinganimation = script:WaitForChild("Walking")
local WalkAnim = humanoid:LoadAnimation(walkinganimation)
local chasingplayer = false
local TS = game:GetService("TweenService")
local currenttarget = nil
--local RepS = game:GetService("ReplicatedStorage")
--local Players = game:GetService("Players")
--local LE = RepS:WaitForChild("LightEvent")
--local SLE = RepS:WaitForChild("StopLightEvent")
local clicking = char.HumanoidRootPart.Sound
local scream = char.HumanoidRootPart.Scream
clicking:Play()
WalkAnim:Play()
local fadeout = TS:Create(scream, TweenInfo.new(1.0, Enum.EasingStyle.Linear), {Volume = 0})
local function findNearestPlayer()
local nearestPlayer = nil
local shortestDistance = 200
for _, thing in pairs(workspace:GetChildren()) do
if thing:IsA("Model") and thing ~= char and thing:FindFirstChild("Humanoid") and thing.IsPatient.Value == true and thing.Humanoid.Health ~= 0 and thing.BreakingRule.Value == true then
thing.BeingChased.Value = true
currenttarget = thing
local hrp = thing.HumanoidRootPart
local distance = (char.HumanoidRootPart.Position - hrp.Position).Magnitude
if distance <= shortestDistance then
nearestPlayer = thing
shortestDistance = distance
end
end
end
return nearestPlayer
end
humanoid.Touched:Connect(function(part)
if part.Parent:FindFirstChild("Humanoid") and part.Parent.Name ~= "Worker" and part.Parent.IsPatient.Value == true then
part.Parent.Humanoid.Health = 0
end
end)
local target = nil
local path = nil
task.spawn(function()
while always do
--if chasingplayer == false then
-- WalkAnim:Stop()
--end
target = findNearestPlayer()
if not target then
target = destinations[math.random(1, #destinations)]
end
--if chasingplayer == false then
-- WalkAnim:Play()
--end
path = pathFinder:CreatePath()
if target:IsA("Model") and target.Humanoid.Health ~= 0 then
path:ComputeAsync(char.HumanoidRootPart.Position, target.HumanoidRootPart.Position)
if chasingplayer == false then
scream.Volume = 7.797
scream:Play()
end
--local hitPlayer = Players:GetPlayerFromCharacter(target)
--LE:FireClient(hitPlayer)
chasingplayer = true
else
path:ComputeAsync(char.HumanoidRootPart.Position, target.Position)
if chasingplayer == true then
fadeout:Play()
chasingplayer = false
if currenttarget ~= nil then
currenttarget.BeingChased.Value = false
--local hitPlayer = Players:GetPlayerFromCharacter(currenttarget)
--SLE:FireClient(hitPlayer)
currenttarget = nil
end
end
end
wait(0.1)
end
end)
task.spawn(function()
while always do
wait(0.1)
for _, wayPoint in pairs(path:GetWaypoints()) do
char.Humanoid:MoveTo(wayPoint.Position)
if wayPoint.Action == Enum.PathWaypointAction.Jump then
char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
if target:IsA("Model") and target ~= char and target.IsPatient.Value == true and (char.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude <= 2 then
print("Player found.")
chasingplayer = false
target.BeingChased.Value = false
char.Humanoid:MoveTo(target.HumanoidRootPart.Position)
break
end
end
end
end
)
I tried doing loops at the same time like you suggested, but when the game runs, the script throws a time out error, forcing me to add wait(0.1) to both loops to get it to work. Obviously, adding wait(0.1) to the second loop wouldn’t help the freezing issue.
I also dont know what **character.PrimaryPart.AssemblyLinearVelocity ** is and don’t know how to incorporate it, char.PrimaryPart:SetNetworkOwner(nil) is only in there because it was in the tutorial i read to create a wandering ai