As the title says, how I implement a grid positioning system having an isometric camera, as the viewport raycast is not possible as the camera is fixed on one of the axes.
My Code:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local SoundService = game:GetService("SoundService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Mouse = Player:GetMouse()
local Camera = game.Workspace.CurrentCamera
local Assets = ReplicatedStorage:WaitForChild("Assets")
local PreviewPart = Assets.PreviewPart
local Zoom = 150
local FoV = 7
local preview = nil
local PlayerController = {}
local function CreatePreviewPart()
preview = PreviewPart:Clone()
preview.Parent = workspace
end
local function RenderPreview()
end
function PlayerController:Init()
local controls = require(Player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule")):GetControls()
controls:Disable()
self:EnableCustomMovement()
CreatePreviewPart()
Camera.CameraType = Enum.CameraType.Custom
RunService.RenderStepped:Connect(function()
Camera.FieldOfView = FoV
if Character then
if Character:FindFirstChild("Head") then
SoundService:SetListener(Enum.ListenerType.ObjectCFrame, Character.Head)
Camera.CFrame =
CFrame.new(Vector3.new(Character.Head.Position.X + Zoom, Character.Head.Position.Y + Zoom, Character.Head.Position.Z + 100), Character.Head.Position)
end
end
end)
RunService:BindToRenderStep("Preview", Enum.RenderPriority.Camera.Value, RenderPreview)
end
function PlayerController:EnableCustomMovement()
Mouse.Button1Down:Connect(function()
print("Move to Position")
end)
end
return PlayerController
Sorry for not explaining it correctly. The part created with CreatePreviewPart should be correctly aligned to the ground in RenderPreview().
Full Code (As I had previously deleted the old RenderPreview code, it is not aligned in a grid but if I can solve this, aligning it in a grid is easy):
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local SoundService = game:GetService("SoundService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Mouse = Player:GetMouse()
local Camera = game.Workspace.CurrentCamera
local Assets = ReplicatedStorage:WaitForChild("Assets")
local PreviewPart = Assets.PreviewPart
local Zoom = 150
local FoV = 7
local preview = nil
local PlayerController = {}
local function CreatePreviewPart()
preview = PreviewPart:Clone()
preview.Parent = workspace
end
local function RenderPreview()
local mousePos = UserInputService:GetMouseLocation()
local unitRay = Camera:ViewportPointToRay(mousePos.X, mousePos.Y)
local rayCast = workspace:Raycast(unitRay.Origin, unitRay.Direction * 1000)
if rayCast and preview then
preview.Position = rayCast.Position
end
end
function PlayerController:Init()
local controls = require(Player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule")):GetControls()
controls:Disable()
self:EnableCustomMovement()
CreatePreviewPart()
Camera.CameraType = Enum.CameraType.Custom
RunService.RenderStepped:Connect(function()
Camera.FieldOfView = FoV
if Character then
if Character:FindFirstChild("Head") then
SoundService:SetListener(Enum.ListenerType.ObjectCFrame, Character.Head)
Camera.CFrame =
CFrame.new(Vector3.new(Character.Head.Position.X + Zoom, Character.Head.Position.Y + Zoom, Character.Head.Position.Z + 100), Character.Head.Position)
end
end
end)
RunService:BindToRenderStep("Preview", Enum.RenderPriority.Camera.Value, RenderPreview)
end
function PlayerController:EnableCustomMovement()
Mouse.Button1Down:Connect(function()
print("Move to Position")
end)
end
return PlayerController
There is no code, they are in the workspace in the grid folder. In this case, my system is to move on the grid, when clicking on the block your character would move there. And it would be a limited space, at the moment each block of the grid is a separate part as I thought it would facilitate the creation of this system.
Oh and about the colors, I left them like this just to make it easier to differentiate between each block
local function RenderPreview()
local mousePos = UserInputService:GetMouseLocation()
local unitRay = Camera:ScreenPointToRay(mousePos.X, mousePos.Y)
local hitGridPart = nil
for _, gridPart in ipairs(workspace.Grid:GetChildren()) do
local rayCast = workspace:Raycast(unitRay.Origin, (gridPart.Position - unitRay.Origin).unit * 1000)
if rayCast and rayCast.Instance == gridPart then
hitGridPart = gridPart
break
end
end
if hitGridPart and preview then
preview.Position = hitGridPart.Position
end
end
If yes, this doesn’t works.
I make a test with this code:
local function RenderPreview()
local mousePos = UserInputService:GetMouseLocation()
local unitRay = Camera:ScreenPointToRay(mousePos.X, mousePos.Y)
local rayCast = workspace:Raycast(unitRay.Origin, unitRay.Direction * 1000)
if rayCast and preview then
local hitPart = rayCast.Instance
print(hitPart)
if hitPart:IsDescendantOf(workspace.Grid) then
preview.Position = hitPart.Position
end
end
end
Console Log (It’s not printing the part my mouse is on, but parts of the character):
- PlayerController:30
21:12:16.460 Head - Cliente - PlayerController:30
21:12:16.503 Head - Cliente - PlayerController:30
21:12:16.516 Head - Cliente - PlayerController:30
21:12:16.542 Head - Cliente - PlayerController:30
21:12:16.583 Head - Cliente - PlayerController:30
21:12:16.599 Head - Cliente - PlayerController:30
21:12:16.627 Head - Cliente - PlayerController:30
21:12:16.668 Head - Cliente - PlayerController:30
21:12:16.678 Head - Cliente - PlayerController:30
21:12:16.710 Head - Cliente - PlayerController:30
21:12:16.757 Head - Cliente - PlayerController:30
21:12:16.768 Head - Cliente - PlayerController:30
21:12:16.796 Head - Cliente - PlayerController:30
21:12:16.832 Head - Cliente - PlayerController:30
21:12:16.846 Head - Cliente - PlayerController:30
I managed to fix it, for those who are still curious about how to do it.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local blockTemplate = ReplicatedStorage:FindFirstChild("BlockTemplate")
local gridSize = 8
local previewBlock = blockTemplate:Clone()
previewBlock.Transparency = 0.5
previewBlock.CanCollide = false
previewBlock.Parent = workspace
local function roundToGrid(value, gridSize)
return math.floor(value / gridSize + 0.5) * gridSize
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)