Unable to move part on where the mouse is aiming at

How to let a part follow mouse on server?

My current problem is that I can’t let the part move at all on the server when I fire a Remote Event.


What are you to really solve?

A part that can follow the mouse’s position on the server.

Ok, we see what are you trying to do. Any scripts?

Yes but I’ll only include a few lines

Any solutions you found on the Developer Forum?

Nope!
No solutions I have found that would be helpful.

Script

local replicatedstorage____again = game:GetService('ReplicatedStorage')
local game_run_service = game:GetService('RunService')

local function create_a_new_part(Player)
	local part = Instance.new('Part')
	part.Name = 'Brick'
	part.Parent = workspace
	part.Material = 'Brick'
    
    local Mouse = Player:GetMouse()
	game_run_service.Stepped:Connect(function()
		part.Position = CFrame.new(Mouse.X, Mouse.Y)
	      
		end)
	end

replicatedstorage____again.CreateEvent.OnServerEvent:Connect(create_a_new_part)

Do you have any errors?

Yes. 20:40:20.806 - ServerScriptService.Script:12: attempt to index nil with ‘X’

What Current Solutions have you tried?

Changing the parameters in the function. We have defined a player, I tried defining a mouse but I had redo this on Player:GetMouse and I don’t believe it works on the server and Client only.

The player’s mouse is client-sided, so it can only be seen on their client and the server won’t have any access to it. One solution that you can try doesn’t need a remote event at all, but you need to understand the concept of:

Network Ownership

So, the server doesn’t handle all of the physics of parts in the workspace, the work is divided among the server and client, so they’ll have to calculate the physics and they’ll be sent over with a negligible delay. By default, all parts have their owner set to Auto, where the engine decides whether to give a client or server network ownership; the closest client to the part within a certain distance is given network ownership, but if none are close by, the server does the physics calculation

In this case, you’d want to give the client network ownership of the created part and when the part is moved on the player’s client (as long as it’s not anchored), the change will be replicated to the server, and therefore to all clients. We can do this using SetNetworkOwner which takes one argument: the client to give network ownership of the part, or the server (if nil was passed as an argument)


Your server code should look like this:

local replicatedstorage____again = game:GetService('ReplicatedStorage')
local game_run_service = game:GetService('RunService')

local function create_a_new_part(Player)
	local part = Instance.new('Part')
	part.Name = 'Brick'
    part.Material = 'Brick'
	part.Parent = workspace
    part:SetNetworkOwner(Player)
end

replicatedstorage____again.CreateEvent.OnServerEvent:Connect(create_a_new_part)

I have better results now it’s just that the parts move the Opposite direction of the mouse.

https://gyazo.com/18de113ea143ea3b9ebf306b12247ba1

as of so far the part doesn’t fall out of the workspace, it just jumps back in position when you hit your mouse button again

https://gyazo.com/999f38aa2f45b462e621703d95cec92c

What does the local script look like?

ok

local createbutton__index = script.Parent
local player_localplayer = game.Players.LocalPlayer
local player_mouse = player_localplayer:GetMouse()
local db = false

local game_run_service = game:GetService('RunService')

local mouseisdown = false

local function enableDragging()
	player_mouse.Button1Down:Connect(function()
		mouseisdown = true
		end)
			player_mouse.Button1Up:Connect(function()
				mouseisdown = false
				end)
end

local function createPart()
	createbutton__index.MouseButton1Click:Connect(function()
		if db == false then
		local brick = game.ReplicatedStorage.Furniture.Brick:Clone()
		brick.Parent = workspace
		db = true
		delay(5,function()
			db = false
			end)
		
		game_run_service.RenderStepped:Connect(function()
			if mouseisdown then
				player_mouse.TargetFilter = brick
				brick.Position = Vector3.new(player_mouse.X, player_mouse.Y) + Vector3.new(player_localplayer.Character.Head.Position)
				end
			end)
				end
		end)
end

-- Loaders --
createPart()
enableDragging()

while true do
	wait(30)
	game.ReplicatedStorage.Furniture:Destroy()
	wait(2)
	script.Parent.Parent.Furniture:Clone().Parent = game.ReplicatedStorage
end

Is there a reason why you’re avoiding moving the brick along the z axis? Furthermore why are you adding the player’s head position into it?

i forgot about the z axis, should i move it to Mouse.Hit.p instead of following?

I don’t think there’s one for Z for mouse.Z

That’d likely fix your issue. As well as removing the player head positioning as that can mess with where you want the block.

Edit: Again, don’t really know why that was there.

The mouse x and y are likely referring to the mouse’s actual UDim 2 position on screen. Use Mouse.Hit to get the mouse’s contacting CFrame. Use Mouse.Hit.p if you just want the Vector3.

:white_check_mark: All works, just wondering the part collides half way in another part

That’s a whole other issue. If you’re just wanting to move it above the ground I’d suggest adding the size’s y divided by 2 to it. If, however, you want it to outright avoid collisions with parts I’d recommend looking into normals and offsetting via normal * size/2 which should work.

Which part would I change?

if (humanoid_rootpart.Position - brick.Position).Magnitude < 15 then
				if player_mouse.Target.Name == 'Brick' then
				brick.Position = Vector3.new(player_mouse.Hit.p.X, player_mouse.Hit.p.Y, player_mouse.Hit.p.Z)

btw if the target name was brick it would keep bouncing the part to the camera

You can do either case by simply adding the offset to the end product.

If you want to generate a Normal to offset the part from another part simply check if a player_mouse.Target exists, and use it to construct a new Direction vector via Vector3.FromNormalId(player_mouse.TargetSurface). Multiply that by the size divided by 2 and you should get the appropriate amount to offset your part assuming no rotation is involved.

So in total your to add this to your position it should look roughly like this:

if player_mouse.Target ~= nil then
    brick.Position = player_mouse.Hit.p + (Vector3.FromNormalId(player_mouse.TargetSurface) * brick.Size/2)
else
    brick.Position = player_mouse.Hit.p
end

This is assuming your part is NOT rotated. Math gets a little off at that point.

Also if you want to ignore the brick to prevent it from, “Bouncing the part to the Camera” you can set player_mouse.TargetFilter to the brick.

It’s what I did when setting the Mouse’s TargetFilter, but the part would be dragged for about 1 second then drop back down, Cannot be redragged again.

here, here’s the whole code so you know what am on about

local createbutton__index = script.Parent
local player_localplayer = game.Players.LocalPlayer
local humanoid_rootpart = player_localplayer.Character:WaitForChild('HumanoidRootPart')
local player_mouse = player_localplayer:GetMouse()
local db = false

local game_run_service = game:GetService('RunService')

local mouseisdown = false

local function enableDragging()
	player_mouse.Button1Down:Connect(function()
		mouseisdown = true
		end)
			player_mouse.Button1Up:Connect(function()
				mouseisdown = false
				end)
end

local function createPart()
	createbutton__index.MouseButton1Click:Connect(function()
		if db == false then
		local brick = game.ReplicatedStorage.Furniture.Brick:Clone()
		brick.Parent = workspace
		db = true
		delay(5,function()
			db = false
			end)
		
		game_run_service.RenderStepped:Connect(function()
			if mouseisdown then
				if (humanoid_rootpart.Position - brick.Position).Magnitude < 15 then
				if player_mouse.Target.Name == 'Brick' then
				brick.Position = Vector3.new(player_mouse.Hit.p.X, player_mouse.Hit.p.Y, player_mouse.Hit.p.Z)
				end
				end
				end
			end)
				end
		end)
end


-- Loaders --
createPart()
enableDragging()

while true do
	wait(30)
	game.ReplicatedStorage.Furniture:Destroy()
	wait(2)
	script.Parent.Parent.Furniture:Clone().Parent = game.ReplicatedStorage
end

instead of using Hit.p use Hit.Position, p is depreciated

1 Like

when Hit.p is deprecated and finally see. Ah. I thought something was wrong and why Hit.p still existed

The proper explanation is that the p property of the CFrame datatype is deprecated and superseded by Position for both API consistency and having a clear property to reference from. When we refer to Hit.p being deprecated, it is actually meaning CFrame.p is deprecated.

This is relatively off-topic though.

1 Like