local BuildingModule = require(game.ReplicatedStorage.Scripts.BuildingModule)
local Hotels = workspace.Hotels
local PathfindingService = game:GetService("PathfindingService")
local AI = {}
-- IDs for default R15 animations
local DEFAULT_WALK_ANIMATION_ID = "rbxassetid://913402848" -- Default R15 walk animation
local DEFAULT_IDLE_ANIMATION_ID = "rbxassetid://507766666" -- Default R15 idle animation
-- Function to create a straight-line path to the target grid part
function AI.createStraightLinePath(startPosition, targetPosition)
local waypoints = {}
-- Move along the X-axis first
table.insert(waypoints, Vector3.new(targetPosition.X, startPosition.Y, startPosition.Z))
-- Then move along the Z-axis
table.insert(waypoints, Vector3.new(targetPosition.X, startPosition.Y, targetPosition.Z))
return waypoints
end
-- Function to calculate distance between two positions
local function getDistance(pos1, pos2)
return (pos1 - pos2).Magnitude
end
-- Function to find the closest grid part
local function getClosestGridPart(npc, gridParts)
local closestPart = nil
local minDistance = math.huge
for _, gridPart in pairs(gridParts) do
local distance = getDistance(npc.PrimaryPart.Position, gridPart.Position)
if distance < minDistance then
minDistance = distance
closestPart = gridPart
end
end
return closestPart, minDistance
end
-- Function to play animations
function AI.playAnimation(humanoid, animationId)
local animator = humanoid:FindFirstChildOfClass("Animator")
if animator then
local animation = Instance.new("Animation")
animation.AnimationId = animationId
local animationTrack = animator:LoadAnimation(animation)
animationTrack:Play()
return animationTrack
end
end
-- Function to stop animations
function AI.stopAnimation(animationTrack)
if animationTrack then
animationTrack:Stop()
end
end
-- Function to move NPC through grid parts or freely
function AI.moveTo(plr, npc, targetPosition)
local humanoid = npc:FindFirstChildWhichIsA("Humanoid")
if not humanoid then
warn("No humanoid found in NPC.")
return
end
local floor = BuildingModule.getFloorFromObject(npc.PrimaryPart)
if not floor then
floor = 1
end
local gridParts = Hotels[plr.UserId].Floors[floor].FloorGrid.gridParts:GetChildren()
local closestGridPart, distanceToGrid = getClosestGridPart(npc, gridParts)
-- Define a threshold distance to decide when to switch to grid-based movement
local gridProximityThreshold = 10 -- Adjust this value as needed
local walkAnimTrack = AI.playAnimation(humanoid, DEFAULT_WALK_ANIMATION_ID)
if distanceToGrid and distanceToGrid <= gridProximityThreshold then
-- NPC is close to a grid part, move to the closest grid part and snap to it
warn("[DEBUG] NPC is close to a grid part. Snapping to grid system.")
npc.Humanoid:MoveTo(closestGridPart.Position)
npc.Humanoid.MoveToFinished:Wait()
-- Create a straight-line path to the target position in grid-like steps
local waypoints = AI.createStraightLinePath(closestGridPart.Position, targetPosition)
warn("[DEBUG] NPC is using the grid system to move in lines.")
for _, waypoint in ipairs(waypoints) do
npc.Humanoid:MoveTo(waypoint)
npc.Humanoid.MoveToFinished:Wait()
end
else
-- NPC is not close to a grid part, move freely
warn("[DEBUG] NPC is moving freely, not using grid system.")
npc.Humanoid:MoveTo(targetPosition)
npc.Humanoid.MoveToFinished:Wait()
end
-- Stop walking animation and play idle animation
AI.stopAnimation(walkAnimTrack)
AI.playAnimation(humanoid, DEFAULT_IDLE_ANIMATION_ID)
end
return AI
I’ve made a AI Pathfinding system based off of waypoints I already have in my project.
The NPC’s walk in lines, however whenever there is a obstacle it fails to compute a new path.
Any advice?