My Code:
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local blockTemplate = ReplicatedStorage:FindFirstChild("BlockTemplate")
local gridSize = 8
local previewBlock = blockTemplate:Clone()
previewBlock.Transparency = 0.5
previewBlock.CanCollide = false
previewBlock.Parent = workspace
local moving = false
local function roundToGrid(value, gridSize)
return math.floor(value / gridSize + 0.5) * gridSize
end
local function heuristic(a, b)
return (a - b).Magnitude
end
local function getNeighbors(node, gridSize)
local neighbors = {}
local directions = {
Vector3.new(1, 0, 0),
Vector3.new(-1, 0, 0),
Vector3.new(0, 0, 1),
Vector3.new(0, 0, -1)
}
for _, direction in ipairs(directions) do
local neighbor = node + direction * gridSize
table.insert(neighbors, neighbor)
end
return neighbors
end
local function aStar(startPos, goalPos, gridSize)
local openSet = {[startPos] = true}
local cameFrom = {}
local gScore = {[startPos] = 0}
local fScore = {[startPos] = heuristic(startPos, goalPos)}
while next(openSet) do
local current
local lowestFScore = math.huge
for node in pairs(openSet) do
if fScore[node] and fScore[node] < lowestFScore then
lowestFScore = fScore[node]
current = node
end
end
if current == goalPos then
local path = {}
while cameFrom[current] do
table.insert(path, 1, current)
current = cameFrom[current]
end
return path
end
openSet[current] = nil
for _, neighbor in ipairs(getNeighbors(current, gridSize)) do
local tentativeGScore = gScore[current] + heuristic(current, neighbor)
if not gScore[neighbor] or tentativeGScore < gScore[neighbor] then
cameFrom[neighbor] = current
gScore[neighbor] = tentativeGScore
fScore[neighbor] = gScore[neighbor] + heuristic(neighbor, goalPos)
openSet[neighbor] = true
end
end
wait()
end
return nil
end
local function moveToGridPosition(gridPosition)
if moving then
humanoid:MoveTo(rootPart.Position)
moving = false
end
local startPos = Vector3.new(
roundToGrid(rootPart.Position.X, gridSize),
roundToGrid(rootPart.Position.Y, gridSize),
roundToGrid(rootPart.Position.Z, gridSize)
)
local path = aStar(startPos, gridPosition, gridSize)
if path then
moving = true
for _, waypoint in ipairs(path) do
if not moving then break end
humanoid:MoveTo(waypoint)
humanoid.MoveToFinished:Wait()
wait()
end
moving = false
else
warn("Path not found!")
end
end
UserInputService.InputBegan:Connect(function(input, gameProcessed)
if input.UserInputType == Enum.UserInputType.MouseButton1 and not gameProcessed then
local mousePos = mouse.Hit.p
local gridPos = Vector3.new(
roundToGrid(mousePos.X, gridSize),
roundToGrid(mousePos.Y, gridSize),
roundToGrid(mousePos.Z, gridSize)
)
moveToGridPosition(gridPos)
end
end)
local function onUpdate()
local mouseRay = mouse.UnitRay
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {workspace.Grid}
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 1000, raycastParams)
if raycastResult then
local hitPos = raycastResult.Position
local gridPos = Vector3.new(
roundToGrid(hitPos.X, gridSize),
roundToGrid(hitPos.Y, gridSize),
roundToGrid(hitPos.Z, gridSize)
)
previewBlock.Position = gridPos
end
end
RunService.RenderStepped:Connect(onUpdate)