Hi everybody. I’m working on a custom pathfinding system using BezierPath and Roblox’s built-in pathfinding system. I am having a hard time figuring out whether I should do my BezierPath path calculations via server or client. Which do you think I should use?
Here is my current code:
local AStar = require(script.Pathfinder)
local BezierPathModule = require(script.BezierPath)
local Enums = require(script.Enums)
local Information = require(script.Information)
local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")
local EntityDatabase = {}
local Utils = {}
local Pathfinders = {}
local OverallDeltaTime = 0
local DeltaLimit = 10
local DeltaCount = 0
function Utils:GetOrigin(Info, Height) : Vector3
return Vector3.new(Info.BoundsX[1]+Info.BoundsX[2], Height, Info.BoundsZ[1]+Info.BoundsZ[2])
end
function Utils:SpawnToDatabase(Name, Height)
local Properties = {}
for Property, PropertyValue in pairs(Information[Name]) do
Properties[Property] = PropertyValue
end
Properties["CFrame"] = CFrame.new(Utils:GetOrigin(Information[Name], Height))
Properties["ID"] = #EntityDatabase + 1
Properties["Traveling"] = false
Properties["TravelTime"] = 0
Properties["Target"] = nil
table.insert(EntityDatabase, Properties)
end
function Utils:SortBounds(Info)
local xMin, xMax = math.min(Info.BoundsX[1], Info.BoundsX[2]), math.max(Info.BoundsX[1], Info.BoundsX[2])
local zMin, zMax = math.min(Info.BoundsZ[1], Info.BoundsZ[2]), math.max(Info.BoundsZ[1], Info.BoundsZ[2])
return {xMin, xMax}, {zMin, zMax}
end
function Pathfinders:WanderPath(Info, Height)
local xBounds, zBounds = Utils:SortBounds(Info)
local OriginX = Utils:GetOrigin(Info,Height).X
local OriginZ = Utils:GetOrigin(Info,Height).Z
local PositionX = OriginX + math.random(xBounds[1], xBounds[2])
local PositionZ = OriginZ + math.random(zBounds[1], zBounds[2])
local GoalPosition = Vector3.new(PositionX, Height, PositionZ)
local GoalPath = PathfindingService:CreatePath()
GoalPath:ComputeAsync(Info.CFrame.Position, GoalPosition)
local PathWaypoints = GoalPath:GetWaypoints()
local WaypointPositions = {}
if GoalPath.Status == Enum.PathStatus.Success then
for Index, Waypoint in pairs(PathWaypoints) do
table.insert(WaypointPositions, Waypoint.Position)
end
local NewBezierPath = BezierPathModule.new(WaypointPositions, 3)
local PathLength = NewBezierPath:GetPathLength()
local PathTime = PathLength / Info.Speed
return NewBezierPath, PathLength, PathTime
else
warn("Path unsuccessful \n ---INFO--- \n" .. "Entity ID ... " .. tostring(Info.ID) .. "\n Position .... " .. tostring(Info.CFrame))
wait(1)
Pathfinders:WanderPath(Info, Height)
return
end
end
Utils:SpawnToDatabase("Anigorix", 0)
RunService.Heartbeat:Connect(function(DeltaTime)
OverallDeltaTime += DeltaTime
DeltaCount += 1
for EntityName, EntityInfo in pairs(EntityDatabase) do
if EntityInfo.Traveling then
EntityInfo.TravelTime += DeltaTime
end
end
if DeltaCount >= DeltaLimit then
for EntityName, EntityInfo in pairs(EntityDatabase) do
if not EntityInfo.Traveling or not EntityInfo.Target then
EntityInfo.Traveling = true
local BezierPath, PathLength, PathTime = Pathfinders:WanderPath(EntityInfo, 0)
EntityInfo.CFrame = BezierPath:CalculateUniformCFrame(1/(DeltaCount*DeltaLimit))
if EntityInfo.TravelTime >= PathTime then
EntityInfo.Traveling = false
EntityInfo.TravelTime = 0
print("done traveling")
end
end
end
workspace.R6.PrimaryPart.CFrame = EntityDatabase[1].CFrame -- testing purposes
DeltaCount = 0
end
end)
Any ideas do help! Thank you!