I want to make a simple script that makes Humanoid
chase the player. One thing is that I have no clue how can I implement a proper following. I tried PathfindingService
, but it is insanely jittery and sometimes gets stuck on walls. Is there any other way or a workaround?
That is still very jittery.
Post must be at least 30.
Have you tried the button?
SetNetworkOwner
would be your Friend here, It helps Remove some of the “Stuttering” from the NPC, The function can only be applied to BaseParts
that are unanchored, so for the NPC, you need to Apply to its Root, which is the HumanoidRootPart
HumanoidRootPart:SetNetworkOwner(nil)
-- Gives ownership to the Server
I Recommend Looking into it, Here is some Documentation if you are interested in that
I already have it in my script.
Hmph, works fine for me, can you send a video?
I can’t send a video for some reason. It says “failed to upload”.
Is it behaving like this? Because im also having the same issue
Not a bit like that. It doesn’t turn around or anything, it just kind of stops and then starts moving again.
The question is still open. I would appreciate any help.
whats your code? where is this being run on, server or client. its hard to figure out the problem without more detail
that stuffs PERSONAL!!1!1! i can’t show u anything >:c
The code is parented to the model and the script is this.
local Players = game:GetService("Players")
local Pathfinding = game:GetService("PathfindingService")
local model = script.Parent
local primPart = model.PrimaryPart
local humanoid = model:WaitForChild("Humanoid")
humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff
humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
for _, v:Instance in ipairs(model:GetDescendants()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
local lastPosition = Vector3.new(math.huge, math.huge, math.huge)
local isStuck = false
local function Follow(target:Model, distance:number)
local root = target.PrimaryPart
if root == nil then return end
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {model, target}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local rayResult = workspace:Raycast(primPart.Position, root.Position, raycastParams)
--i had an idea of maybe checking if the path between player and npc is obstructed.
--but, it ended up working incorrectly, serving no use.
if true then --currently a placeholder
local path:Path = Pathfinding:CreatePath({
AgentCanClimb = true,
Costs = {
Climb = 2
}
})
if path then
local destination = root.Position
local success, err = pcall(function()
path:ComputeAsync(primPart.Position, root.Position)
end)
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
if #waypoints < 2 then return end
if not isStuck then
local startWP:PathWaypoint = waypoints[1]
local waypointsToGoThrough = {waypoints[2]}
for i, wp:PathWaypoint in ipairs(waypoints) do
if i <= 2 then continue end
if (wp.Position - startWP.Position).Magnitude < 1 then
table.insert(waypointsToGoThrough, wp)
else
break
end
end
for i, wp in ipairs(waypointsToGoThrough) do
humanoid:MoveTo(wp.Position)
end
else
for i, wp:PathWaypoint in ipairs(waypoints) do
if i == 1 then continue end
humanoid:MoveTo(wp.Position)
local moved = false
local conn = humanoid.MoveToFinished:Connect(function(reached)
if reached then
moved = true
end
end)
local startedMoving = tick()
repeat wait() until tick()-startedMoving >= 0.2 or moved
if not moved then
model:PivotTo(CFrame.new(wp.Position))
end
conn:Disconnect()
end
isStuck = false
end
print((lastPosition-primPart.Position).Magnitude, isStuck)
if (lastPosition-primPart.Position).Magnitude < 0.1 then
isStuck = true
else
isStuck = false
end
lastPosition = primPart.Position
else
warn(err)
end
end
end
end
local function GetClosest(maxDist:number)
local closest = nil
local dist = maxDist
for i, v in ipairs(workspace:GetChildren()) do
if v:IsA("Model") then
local rp:Part = v.PrimaryPart
local plr = Players:GetPlayerFromCharacter(v)
if rp and plr then
local distance = (rp.Position - primPart.Position).Magnitude
if distance < dist then
dist = distance
closest = v
end
end
end
end
return closest, dist
end
while wait() do
local targ:Model, dist:number = GetClosest(200)
if dist > 20 then
humanoid.WalkSpeed = 8
else
humanoid.WalkSpeed = 20
end
if targ then
Follow(targ, dist)
end
end
I had an idea of maybe trying to check if the target.PrimaryPart
and primPart
are obstructed using workspace:Raycast
. It ended up making false detections, and being useless overall.
when you are not stuck you are looping through all of the waypoints and moving to each one without waiting
make sure to wait until move to is finished before moving to the next waypoint
…
If you will keep reading the code, you will actually see that it waits 0.3 secs
after moving to each waypoint. In that case, I can check if the NPC has reached the waypoint and teleport it if not.
I want to stick with one of my ideas. I want to check if the path between target and model is obstructed, if not, I will use Pathfinding
. Otherwise I will just move to the model.
But I can’t seem to figure out a way to check that. Raycasting failed greatly.
theres no wait(.3) in the script anywhere… but ok
could you send a video so i can understand more of your problem
use streamable (its a website) to send the video
(upload to streamable, copy link, paste)
@blorbee this is the waiting sequence. I will try sending video.
but that isnt the area i was talking about, im saying when you are NOT stuck
for i, wp in ipairs(waypointsToGoThrough) do
humanoid:MoveTo(wp.Position)
end
you are never waiting for the move to to be finished, so it justs keeps going through the loop changing the move to position until it hits the last one THEN it moves on with the rest of the function
.MoveToFinished:Wait()
makes it even worse. Trust me.
Try this tutorial. I’m not exactly sure why you chose to handle your pathfinding the way you did, but the method in this tutorial seems to be the straightforward way to go about it. There are also video examples showing that the movement is pretty smooth while using the MoveToFinished
event.