I’ve been working on my own following NPC script and it’s being working really well. All I need now is for some tips to improving it further, and making it the best it can be.
Feedback much appreciated!
Code:
local PathfindingService = game:GetService("PathfindingService") --To Pathfind
local runservice = game:GetService("RunService") --RunService
local Humanoid = script.Parent.Humanoid --Humanoid
local HumanoidRootPart = script.Parent.HumanoidRootPart --Hrp
local MaxDistance = 500 -- Max Distance the NPC Can search (Magnitude)
local DebrisService = game:GetService("Debris")
local DebuggingMode = false -- Shows Path NPC Calculates
local Character = Humanoid.Parent
local RayToCheck = Ray.new(HumanoidRootPart.Position , Vector3.new(0,0, MaxDistance)) --Creating the ray down from the character
local HasWandered = false --Not needed now, will use when i make wander function work
----FUNCTIONS -----
function FindClosestTarget(MaxDist, TableOfCurrentPlayers) ---Compare Player Distances to work out closest player
local Target
local SmallestDistance = MaxDist
local PlayerWithSmallerDistance
for _, player in pairs(TableOfCurrentPlayers) do
local distance = player:DistanceFromCharacter(HumanoidRootPart.Position)
if distance < SmallestDistance then
SmallestDistance = distance
PlayerWithSmallerDistance = player
end
end
Target = PlayerWithSmallerDistance
if Target ~= nil then --Check if it isn't nil
print(Target.Name)
end
return Target
end
function MoveToTarget(Target) --To Move Directly to target if On Ray
if Target then
local Target_Char = Target.Character or Target.CharacterAdded:Wait()
if Target_Char ~= nil and Target_Char:IsA("Model") then
local HRP = Target_Char:WaitForChild("HumanoidRootPart", 5)
if HRP then
Humanoid:MoveTo(HRP.Position)
end
end
end
end
function PathfindToTarget(Target) --To Pathfind To Target if not on ray
if Target then
local Target_Char = Target.Character or Target.CharacterAdded:Wait()
if Target_Char ~= nil and Target_Char:IsA("Model") then
local Target_HRP = Target_Char:WaitForChild("HumanoidRootPart",5)
local path = PathfindingService:CreatePath()
path:ComputeAsync(HumanoidRootPart.Position, Target_HRP.Position)
if path.Status == Enum.PathStatus.Success and DebuggingMode then
local WaypointsTable = path:GetWaypoints()
for i, waypoint in pairs(WaypointsTable) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6, 0.6, 0.6)
part.Position = waypoint.Position
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
if waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
DebrisService:AddItem(part, 5)
Humanoid:MoveTo(waypoint.Position)
end
else
local WaypointsTable = path:GetWaypoints()
for i, waypoint in pairs(WaypointsTable) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
Humanoid:MoveTo(waypoint.Position)
end
end
else
pcall(function()
PathfindToTarget()
end)
end
end
end
function Iterate() --Used to stop jittery pathfinding
for _, v in pairs(script.Parent:GetChildren()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
end
function CheckRayCollisions(RayToCheck, Ray_Hit) --Self Explanotory
local Closest_Plr
Closest_Plr = FindClosestTarget(MaxDistance, game.Players:GetPlayers())
if Closest_Plr ~= nil then
if Ray_Hit then
if Ray_Hit.Parent == Closest_Plr.Character or Closest_Plr.CharacterAdded:Wait() then
return game.Players:GetPlayerFromCharacter(Ray_Hit.Parent)
else
return nil
end
end
end
end
-----------------------
--MAIN CODE---
Iterate()
runservice.Heartbeat:Connect(function() ---Main Part
local Ray_Hit = workspace:FindPartOnRay(RayToCheck, Character)
local Target = FindClosestTarget(MaxDistance, game.Players:GetPlayers())
if Target ~= nil then
if CheckRayCollisions(RayToCheck,Ray_Hit) ~= nil and CheckRayCollisions(RayToCheck) == Target then
MoveToTarget(Target)
else
PathfindToTarget(Target)
end
else
if not HasWandered then
repeat wait() until HasWandered == true
else
wait(1)
HasWandered = false
end
end
end)
-------------