So I need help with my police npc that chases an npc if the npc is wanted. I use a boolvalue inside the npc. So everything works, but when the npc is not wanted anymore, the police does not know where to go. It just goes crazy.
local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")
local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local WalkSpeed = humanoid.WalkSpeed
local DestinationsFolder = workspace:WaitForChild("Destinations") -- Red Parts in the video
character.PrimaryPart:SetNetworkOwner(nil)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function randomWaypoint()
local waypoint = DestinationsFolder:GetChildren()
local random = waypoint[math.random(1, #waypoint)]
return random
end
local function findTarget()
local nearesttarget
local maxDistance = 500
for i,v in ipairs(workspace:WaitForChild("Npcs"):GetChildren()) do
if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then
if v:FindFirstChild("Wanted") and v:FindFirstChild("Wanted").Value == true then
local distance = (character.PrimaryPart.Position - v.PrimaryPart.Position).Magnitude
if distance <= maxDistance then
nearesttarget = v
maxDistance = distance
end
if distance <= 8 then
end
end
end
end
return nearesttarget
end
local function WalkTo(destination)
local pathParams = {
AgentHeight = character:GetExtentsSize().Y,
AgentRadius = character:GetExtentsSize().Z,
AgentCanJump = false,
Costs = {
Danger = math.huge,
}
}
local path = PathfindingService:CreatePath(pathParams)
local Blocked = false
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination.Position)
end)
if success and path.Status == Enum.PathStatus.Success then
waypoints = path:GetWaypoints()
path.Blocked:Connect(function(blockedWaypointIndex)
Blocked = true
path:ComputeAsync(character.PrimaryPart.Position, destination.Position)
end)
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
repeat
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
until humanoid.MoveToFinished:Wait() or Blocked
else
reachedConnection:Disconnect()
end
end)
end
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
end
end
humanoid:GetPropertyChangedSignal("Health"):Connect(function()
coroutine.wrap(function()
humanoid.WalkSpeed = 16
task.wait(10)
humanoid.WalkSpeed = WalkSpeed
end)()
end)
RunService.Heartbeat:Connect(function()
if findTarget() ~= nil then
humanoid.WalkSpeed = 16
WalkTo(findTarget().PrimaryPart)
else
humanoid.WalkSpeed = WalkSpeed
WalkTo(randomWaypoint())
end
end)
In this video: the police chased the npc with the red highlight. After I turned the bool into false, the police does not know where to go. (I disabled the bool at 9 seconds)
2 Likes
I know the problem but I’m not smart to solve it
RunService.Heartbeat:Connect(function()
if findTarget() ~= nil then
humanoid.WalkSpeed = 16
WalkTo(findTarget().PrimaryPart)
else
humanoid.WalkSpeed = WalkSpeed
WalkTo(randomWaypoint()) <-------
end
end)
1 Like
You can add a flag to check if the police is currently chasing a target, and reset the flag and destination when the target is no longer wanted. You can add the following code to do this:
local isChasing = false
local target = nil
local function findTarget()
target = nil
local nearesttarget
local maxDistance = 500
for i,v in ipairs(workspace:WaitForChild("Npcs"):GetChildren()) do
if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then
if v:FindFirstChild("Wanted") and v:FindFirstChild("Wanted").Value == true then
local distance = (character.PrimaryPart.Position - v.PrimaryPart.Position).Magnitude
if distance <= maxDistance then
nearesttarget = v
maxDistance = distance
end
if distance <= 8 then
end
end
end
end
target = nearesttarget
return nearesttarget
end
RunService.Heartbeat:Connect(function()
if findTarget() ~= nil then
isChasing = true
humanoid.WalkSpeed = 16
WalkTo(findTarget().PrimaryPart)
else
if isChasing then
isChasing = false
humanoid.WalkSpeed = WalkSpeed
WalkTo(randomWaypoint())
end
end
end)
game.Workspace.Npcs.ChildAdded:Connect(function(child)
if child == target and child:FindFirstChild("Wanted") and child:FindFirstChild("Wanted").Value == false then
isChasing = false
humanoid.WalkSpeed = WalkSpeed
WalkTo(randomWaypoint())
end
end)
1 Like
Also, how can I make the npc go to a random destination after reaching it’s destination?
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
repeat
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
until humanoid.MoveToFinished:Wait() or Blocked
else
print("reached")
reachedConnection:Disconnect()
end
end)
1 Like
You can make the NPC go to a random destination by generating a random number within the range of the number of waypoints available, and then using that number as the index for the next waypoint to move to. Here’s an example:
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
local nextIndex = math.random(1, #waypoints)
nextWaypointIndex = nextIndex
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
print("reached")
reachedConnection:Disconnect()
end
end)
1 Like
I was talking about this part:
if reached and nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
repeat
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
until humanoid.MoveToFinished:Wait() or Blocked
else
print("reached") <---------- make it go to a random destination
reachedConnection:Disconnect()
end
1 Like
You can add the following code after print("reached") to make the NPC go to a random destination:
nextWaypointIndex = math.random(#waypoints)
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
This will set nextWaypointIndex to a random index in the waypoints table, and then move the NPC to that position.
1 Like
That would make the NPC ignore the PathParams.
1 Like
Yes, that is correct. If you do not specify the PathParams, the NPC will move towards its destination in a straight line and ignore any obstacles in its path. To have the NPC navigate around obstacles and find the optimal path, you will need to provide PathParams.
1 Like
reachedConnection:Disconnect()
nextWaypointIndex = math.random(#waypoints)
path:ComputeAsync(character.PrimaryPart.Position, waypoints[nextWaypointIndex].Position)
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
I tried this
1 Like
This code will disconnect the current reachedConnection event and then set the nextWaypointIndex to a random value from 1 to the length of the waypoints table. Then, it computes a new path from the character’s current position to the randomly selected waypoint position. Finally, it makes the humanoid move to that random waypoint. This should make the NPC go to a random destination after reaching its current destination.
1 Like
How can I add the PathParams? The code only tells the npc to go to the destination.
1 Like
You can add PathParams to the MoveTo function by passing it as a second argument. For example:
local pathParams = PathParams.new()
humanoid:MoveTo(waypoints[nextWaypointIndex].Position, pathParams)
You can then set the desired values for the PathParams object, such as MaxSpeed , Jump or Rounding to control the way the NPC moves.
For example:
pathParams.MaxSpeed = 10
pathParams.Jump = false
pathParams.Rounding = 10
1 Like
This got an error.
humanoid:MoveTo(waypoints[nextWaypointIndex].Position, pathParams)
Unable to cast value to Object
1 Like
Is this how PathParmas is supposed to be done?
local pathParams = {
AgentHeight = character:GetExtentsSize().Y,
AgentRadius = character:GetExtentsSize().Z,
AgentCanJump = false,
Costs = {
Danger = math.huge,
}
}
2 Likes
This error is likely because MoveTo method only accepts one argument, the destination, and doesn’t have an option to pass additional parameters. To use PathParams while moving the NPC to the destination, you can create a new instance of PathParams and pass it to the ComputeAsync method before calling the MoveTo method. Here’s an example:
local pathParams = PathfindingService:CreatePathParams()
pathParams.AllowSWIM = false
pathParams.Avoidance = 0.5
pathParams.Heuristics = 0.5
pathParams.Jumps = false
pathParams.MaxAcceleration = 0.5
nextWaypointIndex = math.random(#waypoints)
path:ComputeAsync(character.PrimaryPart.Position, waypoints[nextWaypointIndex].Position, pathParams)
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
1 Like
Well it only takes 1 step after the npc reaches it’s destination.
1 Like
yea, that also can work!
another example:
local character = game.Workspace.Character
local humanoid = character.Humanoid
local pathParams = {
AgentHeight = character:GetExtentsSize().Y,
AgentRadius = character:GetExtentsSize().Z,
AgentCanJump = false,
Costs = {
Danger = math.huge,
}
}
-- Create an array of waypoints
local waypoints = {
game.Workspace.Waypoint1,
game.Workspace.Waypoint2,
game.Workspace.Waypoint3
}
-- Choose a random starting waypoint
local nextWaypointIndex = math.random(#waypoints)
-- Connect to the MoveToFinished event
local reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position, pathParams)
else
print("Reached destination")
reachedConnection:Disconnect()
end
end)
-- Start moving to the first waypoint
humanoid:MoveTo(waypoints[nextWaypointIndex].Position, pathParams)
1 Like
The NPC stops moving after reaching it’s destination. (Cop NPC)
2 Likes
This issue could be caused by several things, such as a missing connection to the MoveToFinished event or a failure to recalculate the path. Here’s an updated version of the code that addresses these possible issues:
local function MoveToNextWaypoint()
local pathParams = PathfindingService:CreatePathParams()
pathParams.AllowSWIM = false
pathParams.Avoidance = 0.5
pathParams.Heuristics = 0.5
pathParams.Jumps = false
pathParams.MaxAcceleration = 0.5
nextWaypointIndex = nextWaypointIndex + 1
if nextWaypointIndex > #waypoints then
-- all waypoints have been reached
return
end
local destination = waypoints[nextWaypointIndex].Position
local connection
connection = humanoid.MoveToFinished:Connect(function()
-- NPC has reached the destination, move to the next waypoint
connection:Disconnect()
MoveToNextWaypoint()
end)
path:ComputeAsync(character.PrimaryPart.Position, destination, pathParams)
humanoid:MoveTo(destination)
end
-- start moving to the first waypoint
nextWaypointIndex = 1
MoveToNextWaypoint()
In this updated version, a new local variable connection is created to keep track of the connection to the MoveToFinished event. The connection is disconnected after the NPC has reached its destination, which should ensure that it continues moving to the next waypoint. Additionally, the ComputeAsync method is called before the MoveTo method to ensure that a valid path is always available for the NPC to follow.
1 Like