Hi, Im creating a game and using the “PathFindingService” to move npcs from 1 point to another but the
walk animations are weird.
Here is the code I use,
function CreatePath(Humanoid,Target)
local Parms =
{
AgentHeight = 3.5,
AgentRadius = 2,
AgentCanJump = true
}
local Path = PathFindingService:CreatePath(Parms)
Path:ComputeAsync(Humanoid.Parent.PrimaryPart.Position,Target.Position)
if Path.Status == Enum.PathStatus.Success then
local WayPoints = Path:GetWaypoints()
return Path,WayPoints
end
end
script.Move.Event:Connect(function(Humanoid:Humanoid,Target,Action)
if not Target then return end
local Path,Waypoints = CreatePath(Humanoid,Target)
if not Path or not Waypoints then return end
for _, Point in ipairs(Waypoints) do
if Point.Action == Enum.PathWaypointAction.Jump then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
Humanoid:MoveTo(Point.Position)
Humanoid.MoveToFinished:Wait(2)
end
end)
Anyways to make the running animations smooth? Thanks
The reason that this is not smooth is because when you’re close to your NPCs the server will pass NetworkOwnership over to the nearby player. This is a problem because the server is waiting for the moveto to complete, but the client (player) is responsible for letting the server know. This means that anything the humanoid does is subject to network latency (hence the delay).
A really simple fix for this is to set the HumanoidRootPart or the Humanoid’s RootPart (whatever that may be)'s network ownership to to nil via Part:SetNetworkOwner(nil) See BasePart | Roblox Creator Documentation for more details.
The idea here is that if we force no network ownership of the Humanoid’s root part then the network ownership cannot change. This will ensure that your characters move to the next waypoint nearly instantly.
There are some optimizations with the game being able to be handed off to the various players so you may want to look into that down the road. But this should at least help you to understand the problem.
You can use TweenService to interpolate the humanoid’s position between each waypoint in the path. This will make it have a smoother look.
Here’s an example of how you can use TweenService to do so:
-- Import TweenService
local TweenService = game:GetService("TweenService")
-- Define function to move the humanoid
function CreatePath(Humanoid, Target)
local Parms = {
AgentHeight = 3.5,
AgentRadius = 2,
AgentCanJump = true
}
local Path = PathFindingService:CreatePath(Parms)
Path:ComputeAsync(Humanoid.Parent.PrimaryPart.Position, Target.Position)
if Path.Status == Enum.PathStatus.Success then
local WayPoints = Path:GetWaypoints()
for i, Point in ipairs(WayPoints) do
local MoveTween = TweenService:Create(Humanoid.Parent.PrimaryPart, TweenInfo.new(1), {
CFrame = CFrame.new(Point.Position)
})
MoveTween:Play()
if Point.Action == Enum.PathWaypointAction.Jump then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
MoveTween.Completed:Wait()
end
end
end
-- Connect the Move event
script.Move.Event:Connect(function(Humanoid, Target, Action)
if not Target then
return
end
CreatePath(Humanoid, Target)
end)
Found The solution few hors ago, sorry forgot to update here.
If anyone is wondering, the solution is to only use waypoints that are turns. Here Is a function I used to solve this.
just pass the full waypoints list and it will filter them out.
function GetTunedPath(Path)
if Path == nil then return {} end
local WayPoints = Path:GetWaypoints()
local CurrentDifference = Vector2.new(0,0)
local ImportantWaypoints = {}
for i, Waypoint in ipairs(WayPoints) do
if i == #WayPoints then table.insert(ImportantWaypoints,Waypoint) continue end
if i == 1 then table.insert(ImportantWaypoints,Waypoint) continue end
local CurrentPos = Waypoint.Position
local NextPos = WayPoints[i+1].Position
local Difference = (Vector2.new(CurrentPos.X,CurrentPos.Z) - Vector2.new(NextPos.X,NextPos.Z))
if (CurrentDifference - Difference).Magnitude > 0.2 then
table.insert(ImportantWaypoints,Waypoint)
end
CurrentDifference = Difference
end
return ImportantWaypoints
end