I am not very interested in taking inspiration from Tutorials or copying codes. I want to customize my own Grid placement system from scratch. Only one of the problems is, how can I create that grid? And I would be interested in creating a small grid, let’s say of the size ‘20, 1, 20’, which will sit under the object selected in a GUI, and follow that Object,for example, if I press a wall in my inventory GUI , then a wall will spawn and under that wall, you’ll see a grid of the size I was talking about and go after that selected wall until the player clicks left to put the wall down.
And I also want to make it symmetrical, when you move the object, it should not move very detailed, I mean that the object should move with about 2 studs, as an example:
A player puts a wall on the ground, and he also wants to put a wall next to that previously placed wall, so if I don’t implement that thing with 2 studs, and I make it 0.05 studs(default), then the player will stare at those walls to put them symmetrical, and that’s why you want to put those 2 studs,and i think it is a good idea…
Any recommendations? Suggestions? Advice?Or other else?
If you want to move a part in a grid on a plane, then you’d round the X/GridSize and Z/GridSize to get the closest integer, then multiply that with the GridSize:
local mousePos = reference to your calculated mouse-position
local newX = math.round(mousePos.X/GridSize) * GridSize -- Eliminates floats for X axis
local newX = math.round(mousePos.Z/GridSize) * GridSize -- Eliminates floats for Z axis
Just setting the position of the object based on these will create the snappy grid motion, however I’d highly recommend lerping the position to make it smooth.
Here is some example code which you can have a look at to see what I mean:
local RunService = game:GetService("RunService");
local UIS = game:GetService("UserInputService");
local _GRID = 2;
local _RANGE = 250;
local player = game:GetService("Players").LocalPlayer;
local char = player.Character or player.CharacterAdded:Wait();
local cam = workspace.CurrentCamera;
local part = Instance.new("Part");
part.Anchored = true;
part.CanCollide = false;
part.BrickColor = BrickColor.random();
part.Size = Vector3.one * 4;
part.Parent = workspace;
local _RaycastParams = RaycastParams.new();
_RaycastParams.FilterDescendantsInstances = {char, part};
_RaycastParams.FilterType = Enum.RaycastFilterType.Exclude;
local function update(dt)
local mousePos = UIS:GetMouseLocation();
local mouse2DRay = cam:ViewportPointToRay(mousePos.X, mousePos.Y, 1);
local ray = workspace:Raycast(mouse2DRay.Origin, mouse2DRay.Direction * _RANGE, _RaycastParams);
local finalPos
if ray then
finalPos = ray.Position;
else
finalPos = (mouse2DRay.Origin + mouse2DRay.Direction*_RANGE);
end
local newX = math.round(finalPos.X/_GRID) * _GRID;
local newZ = math.round(finalPos.Z/_GRID) * _GRID;
finalPos = Vector3.new(newX, part.Size.Y*.5, newZ);
part.CFrame = part.CFrame:Lerp(CFrame.new(finalPos), .25 * 60 * dt);
end
RunService.RenderStepped:Connect(update);
instead of math.round, it would probably be better to use math.ceil since it always rounds up, no matter the float, it will yield more consistent results, since math.round might round down, offsetting the grid.