Making an npc that will walk around randomly on a floor, but also not walk off it. I am using pathfindingservice to do this, the only problem was that I needed to get a destination position.
Scraping around here I eventually found that you can use a raycast to find the part you are standing on. This let me use the size and position dictate a boundary of where the npc can walk.
This worked, but then I wanted to make my npc walk to another part. How would I do that?
We need your script to see how you are accomplishing it first.
remember to copy/paste it here, but put 3 backticks (```) before and after so it’ll format correctly.
local zombie=script.Parent
--...
local PFS=game:GetService("PathfindingService")
local params=RaycastParams.new()
params.FilterDescendantsInstances=zombie:GetChildren()
params.FilterType=Enum.RaycastFilterType.Exclude
local hit=workspace:Raycast(zombie.Head.Position,Vector3.new(0,-6,0),params)
print(hit)
local floor=hit.Instance
while wait(math.random(3,7)) do
Xpos=floor.Position.X
Ypos=floor.Position.Y
Zpos=floor.Position.Z
Xsize=floor.Size.X
Ysize=floor.Size.Y
Zsize=floor.Size.Z
local randomXpos=math.random(Xpos-(Xsize/2)+2,Xpos+(Xsize/2)-2)
local randomZpos=math.random(Zpos-(Zsize/2)+2,Zpos+(Zsize/2)-2)
local randomYpos=Ypos+Ysize/2+2
local path=PFS:CreatePath()
path:ComputeAsync(zombie.HumanoidRootPart.Position,Vector3.new(randomXpos,randomZpos,randomYpos))
local waypoints=path:GetWaypoints()
print(waypoints)
for i,Waypoint in ipairs(waypoints) do
zombie.Humanoid:MoveTo(Waypoint.Position)
zombie.Humanoid.MoveToFinished:Wait()
end
end
Well, assuming none of the floors are rotated in at all, you’ve got the walk to random position portion down. You probably want to change what’s currently in the floor loop to a function, and create a new function that makes the zombie move to the next designated floor.
Then, you could assign where the raycast using an attribute or value, but preferably the script would be able to decide where to move on it’s own. Though that depends on what your
local PFS=game:GetService("PathfindingService")
local params=RaycastParams.new()
params.FilterDescendantsInstances=zombie:GetChildren()
params.FilterType=Enum.RaycastFilterType.Exclude
function RaycastFloorTarget(Origin,Direction)
local hit=workspace:Raycast(Origin,Direction,params)
if hit.Instance then
return hit.Instance
else
error("Nothing was hit!") --You may want to change this up.
end
end
function WalkToRandom(tFloor,WanderCount)
local f_Pos = tFloor.Position
local f_Size = tFloor.Size
for iW=0,WanderCount do
local randomXpos=math.random(f_Pos.X-(f_Size.X/2)+2,f_Pos.X+(f_Size.X/2)-2)
local randomZpos=math.random(f_Pos.Z-(f_Size.Z/2)+2,f_Pos.Z+(f_Size.Z/2)-2)
local randomYpos=f_Pos.Y+f_Size.Y/2+2
local path=PFS:CreatePath()
path:ComputeAsync(zombie.HumanoidRootPart.Position,Vector3.new(randomXpos,randomZpos,randomYpos))
local waypoints=path:GetWaypoints()
print(waypoints)
for i,Waypoint in ipairs(waypoints) do
zombie.Humanoid:MoveTo(Waypoint.Position)
zombie.Humanoid.MoveToFinished:Wait()
end
end
end
while wait(math.random(3,7)) do
--There's probably a better way to set the target floor than with a raycast, but that depends on what your game is.
newFloor = RaycastFloorTarget(Zombie.Head.Position,Vector3.new(0,0,0))
WalkToRandom(newFloor,5)
end
Talking about finding the floor by a better way than ray casting, I did try to use stuff like GetPartsInPart and GetTouchingParts, but using that on the left leg returned an empty array.
It depends on what the zombies are supposed to do. If you just want the zombie to wander around whatever it’s standing on, I’d reccomend sticking raycasts.