Destroying part on client freezes parts' physics on server

So I’m making a throwable rock, and I have one created on the client immediately when they click. I then invoke the server to tell the server to create the same rock. I then return the server rock to the client via invoking the client, so the client can destroy the server rock and doesn’t see a second rock on their screen. This process is used so the client throwing the rock can see it be thrown smoothly.

For full disclosure of the code in hopes of finding a solution, the code I used to model the parts’ motion was taken from this post written by EgoMoose.

Rock Hierarchy

ServerRockHandler
local throwRock = script.Parent:WaitForChild("ThrowRock")

local travelTime = 0.5

throwRock.OnServerInvoke = function(player, mousePosition)
	local rock = player.Character:FindFirstChild("Rock")
	if rock and rock:IsA("Tool") then
		local humanoidRootPart = player.Character.HumanoidRootPart
		
		local gravity = Vector3.new(0, -workspace.Gravity, 0)
		local x0 = humanoidRootPart.CFrame * Vector3.new(0, 2, -2)
		
		local v0 = (mousePosition - x0 - 0.5 * gravity * travelTime * travelTime) / travelTime
		
		local actualRock = rock:FindFirstChild("Handle"):Clone()
		
		actualRock.Velocity = v0
		actualRock.CFrame = CFrame.new(x0)
		actualRock.CanCollide = true
		actualRock.Parent = workspace
		
		local deleteRock = throwRock:InvokeClient(player, actualRock)
		rock:Destroy()
	end
	
	return
end
ClientRockHandler
local UserInputService = game:GetService("UserInputService")

local rock = script.Parent
local throwRock = script.Parent:WaitForChild("ThrowRock")

local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local equipped = false

rock.Equipped:Connect(function()
	equipped = true
end)

rock.Unequipped:Connect(function()
	equipped = false
end)

UserInputService.InputBegan:Connect(function(input, gPE)
	if input.UserInputType == Enum.UserInputType.MouseButton1 and not gPE then
		if equipped then
			local mousePos = input.Position
			local mouseRay = workspace.CurrentCamera:ScreenPointToRay(mousePos.X, mousePos.Y)
			local spaceRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000)
			local target, position = workspace:FindPartOnRay(spaceRay, character)
			
			local humanoidRootPart = player.Character.HumanoidRootPart
		
			local gravity = Vector3.new(0, -workspace.Gravity, 0)
			local x0 = humanoidRootPart.CFrame * Vector3.new(0, 2, -2)
			local travelTime = 0.5
			local v0 = (position - x0 - 0.5 * gravity * travelTime * travelTime) / travelTime
			
			local actualRock = rock:FindFirstChild("Handle"):Clone()
			
			actualRock.Velocity = v0
			actualRock.CFrame = CFrame.new(x0)
			actualRock.CanCollide = true
			actualRock.Parent = workspace
			
			throwRock:InvokeServer(position)
		end
	end
end)

throwRock.OnClientInvoke = function(serverRock)
	if serverRock then
		serverRock:Destroy()
	end
	
	return
end

My specific issue seems to come from the following code segment

throwRock.OnClientInvoke = function(serverRock)
	if serverRock then
		serverRock:Destroy()
	end
	
	return
end

or more specifically, this line

serverRock:Destroy()

When this line is commented out, I get the following result,


As you can see, both the client and server rock are visible from the client as expected since the server rock was not deleted on the client. From the servers view, the server rock properly reached its destination.

But not if we do not comment that line out, the following happens,


As shown, the client properly sees only one rock, as the server rock was deleted. The issue is that the server rock seems to just freeze in place.

I’m pretty lost on what’s going on here, so any insight into this issue is welcome!

1 Like

part:SetNetworkOwner(nil) in server script should fix that

1 Like