This should work for you:
[LocalScript]
01 | local model = workspace.Model |
02 | local camera = workspace.CurrentCamera |
04 | game:GetService( "UserInputService" ).InputBegan:connect( function (inputObject) |
05 | if (inputObject.UserInputType ~ = Enum.UserInputType.MouseButton 1 ) then return end |
07 | local mousePosition = inputObject.Position |
09 | local mouseRayUnit = camera:ScreenPointToRay(mousePosition.X, mousePosition.Y) |
10 | local mouseRay = Ray.new(mouseRayUnit.Origin, mouseRayUnit.Direction * 1000 ) |
11 | local _, mouseTarget, _ = workspace:FindPartOnRayWithIgnoreList(mouseRay, { model } ) |
13 | model:MoveTo(mouseTarget) |
Let's dive into what this is doing.
First, we have this line:
1 | local mouseRayUnit = camera:ScreenPointToRay(mousePosition.X, mousePosition.Y) |
What that line does is take the position of the mouse on the screen and convert it into a unit Ray. (If you don't know what a ray is, you'll have to do some research.)
Next, we have this:
1 | local mouseRay = Ray.new(mouseRayUnit.Origin, mouseRayUnit.Direction * 1000 ) |
What that does is take the unit ray and extend it to be 1000 studs long. This code means that whatever is being placed can be, at maximum, 1000 studs away from the camera's position.
Finally, we have this:
1 | local _, mouseTarget, _ = workspace:FindPartOnRayWithIgnoreList(mouseRay, { model } ) |
What this does is attempt to find the first part that intersects with the ray. We extract the position of the part that was found and use that to position the model.
If you're using FilteringEnabled, you'll have to make some tweaks for this to show up for other clients.
You'll also have to add in the rest of the code that you need.
I hope this helps! Good luck.