Grid-Based Movement

I am trying to make a system that moves the player just like click to move, but with 16x16 tiles, the best result i got with AI was this:


Code:

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")

local gridSize = 16
local cooldownActive = false -- Variable to track cooldown state

-- Create a part to represent the grid cell
local gridCell = Instance.new("Part")
gridCell.Size = Vector3.new(gridSize, 0.1, gridSize)
gridCell.Anchored = true
gridCell.CanCollide = false
gridCell.Transparency = 0.5
gridCell.Parent = Workspace

local function getNearestGridPosition(position)
	local x = math.floor(position.X / gridSize + 0.5) * gridSize
	local z = math.floor(position.Z / gridSize + 0.5) * gridSize
	return Vector3.new(x, position.Y, z)
end

local function isClosestGrid(targetPosition)
	local playerPosition = humanoidRootPart.Position
	local nearestGridPosition = getNearestGridPosition(playerPosition)
	local distance = (nearestGridPosition - targetPosition).Magnitude
	local dx = math.abs(nearestGridPosition.X - targetPosition.X)
	local dz = math.abs(nearestGridPosition.Z - targetPosition.Z)
	return (dx == 0 and dz <= gridSize) or (dz == 0 and dx <= gridSize)
end

local function startCooldown()
	cooldownActive = true
	gridCell.BrickColor = BrickColor.new("Bright red")
	task.wait(6) -- 6 seconds cooldown
	cooldownActive = false
end

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 and not gameProcessed and not cooldownActive then
		local mouse = player:GetMouse()
		local targetPosition = getNearestGridPosition(mouse.Hit.Position)

		if isClosestGrid(targetPosition) and targetPosition ~= getNearestGridPosition(humanoidRootPart.Position) then
			humanoid:MoveTo(targetPosition)
			startCooldown() -- Start cooldown after moving
		end
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		local mouse = player:GetMouse()
		local hoverPosition = getNearestGridPosition(mouse.Hit.Position)
		gridCell.Position = hoverPosition + Vector3.new(0, 0, 0) -- Slightly above the ground
		
		if cooldownActive then
			gridCell.BrickColor = BrickColor.new("Bright red")
		elseif isClosestGrid(hoverPosition) and hoverPosition ~= getNearestGridPosition(humanoidRootPart.Position) then
			gridCell.BrickColor = BrickColor.new("Bright yellow")
		else
			gridCell.BrickColor = BrickColor.new("Bright red")
		end
	end
end)

The problem is that the player can go to the tile it’s already on top of, i don’t want that but i can’t manage to fix it.
image
The grids around the player look like that, but i am trying to make this:
image

2 Likes

Hello,

It looks like the issue is that your isClosestGrid function doesn’t correctly prevent the player from clicking on the tile they are already standing on. Your function currently allows movement as long as the clicked tile is adjacent, but it doesn’t explicitly block movement to the current tile.

Fix

Modify your isClosestGrid function so that it returns false if the player is already standing on the target grid position.

local function isClosestGrid(targetPosition)
	local playerPosition = humanoidRootPart.Position
	local nearestGridPosition = getNearestGridPosition(playerPosition)

	-- Prevent moving to the same tile the player is already on
	if nearestGridPosition == targetPosition then
		return false
	end

	local dx = math.abs(nearestGridPosition.X - targetPosition.X)
	local dz = math.abs(nearestGridPosition.Z - targetPosition.Z)

	-- Allow movement only to adjacent tiles
	return (dx == gridSize and dz == 0) or (dz == gridSize and dx == 0)
end

Now, your player should only be able to move to directly adjacent tiles and not stay in place! :rocket:

Let me know if this works :blush:

1 Like

Thanks! That makes it seem the answer was right under my nose all that time! I think I have to analyze my code more frequently :sweat_smile:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.