Interacting with parts on client

I have a script that after interacting with an npc, parts will be put into the workspace (only for the client). I want the player to be able to interact with these parts.

The parts each have a server script to tell if player touched them, which I think is making it so the player cant interact with the part. I don’t know how to have the parts only appear on one client and be interactable with the player (preferably using ontouch). I have tried switching the script to a local script, it doesn’t work.

this is the server script in each of the parts

local part = script.Parent
local canGet = true

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChild('Humanoid')
	if humanoid then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if player and canGet then
			canGet = false
			player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value = player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value + 1
			script.Parent.ParticleEmitter.Enabled = false
			script.Parent.Transparency = 1
			wait(2)
			script.Parent.ParticleEmitter.Enabled = true
			script.Parent.Transparency = 0
			canGet = true
		end
	end
end

part.Touched:Connect(onTouch)

If any of that didn’t make sense then ask and I’ll try and explain it more clearly.

Use a LocalScript, but parent it somewhere else (like PlayerGui, StarterPlayerScripts, or even StarterCharacterScripts) rather than having it a direct child of the part, as LocalScripts do not run in Workspace (unless if it’s under the character), which is presumably the reason why using a LocalScript wasnt working for. And remember to mention where exactly that part is located in Workspace.

Make the touch event on the client too :slight_smile:

What do I do if Its multiple, separate parts?

Use a loop or use CollectionService.

You can make the touch event on the client and if want do something on the server use remoteevent, i think its the best and more simple way.

You can use a for loop to get the specific parts from Workspace. There are 3 ways to go about this: 1. Have all the parts in a Folder located somewhere in Workspace; 2. Insert a BoolValue under each part (although it wouldn’t matter whichever value you’d choose); 3. Use CollectionService (although I don’t have enough experience with this service).

If you want to do Method 1, then insert a folder in Workspace, and parent all the parts under that folder. Then use a for loop to get all the children under that folder, and connect the Touched event to them.
Example:

local MainFol = workspace:WaitForChild("") -- locate your folder here
local canGet = true

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChild('Humanoid')

	if humanoid then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if player and canGet then
			canGet = false
			player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value = player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value + 1
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = false
			end
			otherPart.Transparency = 1
			task.wait(2)
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = true
			end
			otherPart.Transparency = 0
			canGet = true
		end
	end
end

for _, parts in pairs(MainFol:GetChildren()) do
	if parts:IsA("BasePart") then -- checks if the children under the folder is a 'BasePart'
		parts.Touched:Connect(onTouch)
	end
end

-- if you intend to add parts as the game runs, make sure to parent the new part(s) under that folder

MainFol.ChildAdded:Connect(function()
	for _, parts in pairs(MainFol:GetChildren()) do
		if parts:IsA("BasePart") then
			parts.Touched:Connect(onTouch)
		end
	end
end)

Edit:

Now if you decide to do Method 2, then insert a BoolValue under each part involved in what you are trying to accomplish, and name them all the same thing (don’t mind the true/false Value property). Having a folder won’t be necessary. although I’d recommend it as it can actually be more organized.

Here is how your script would look like (without a folder):

local canGet = true

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChild('Humanoid')

	if humanoid then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if player and canGet then
			canGet = false
			player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value = player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value + 1
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = false
			end
			otherPart.Transparency = 1
			task.wait(2)
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = true
			end
			otherPart.Transparency = 0
			canGet = true
		end
	end
end

for _, parts in pairs(workspace:GetDescendants()) do
	if parts:IsA("BasePart") then -- checks if the descendants are a 'BasePart'
		if parts:FindFirstChild("") -- put the name of the 'BoolValue' here
			parts.Touched:Connect(onTouch)
		end
	end
end

-- if you intend to add parts as the game runs, make sure to include another 'BoolValue' in that part.

workspace.ChildAdded:Connect(function()
	for _, parts in pairs(workspace:GetDescendants()) do
		if parts:IsA("BasePart") then
			if parts:FindFirstChild("") -- put the name of the 'BoolValue' here
				parts.Touched:Connect(onTouch)
			end
		end
	end
end)

Edit 2:

And here’s how it should look with a folder (for method 2):

local MainFol = workspace:WaitForChild("") -- locate your folder here
local canGet = true

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChild('Humanoid')

	if humanoid then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if player and canGet then
			canGet = false
			player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value = player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value + 1
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = false
			end
			otherPart.Transparency = 1
			task.wait(2)
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = true
			end
			otherPart.Transparency = 0
			canGet = true
		end
	end
end

for _, parts in pairs(MainFol:GetChildren()) do
	if parts:IsA("BasePart") then -- checks if the children under the folder is a 'BasePart'
		if parts:FindFirstChild("") -- put the name of the 'BoolValue' here
			parts.Touched:Connect(onTouch)
		end
	end
end

-- if you intend to add parts as the game runs, make sure to include another 'BoolValue' in that part.

MainFol.ChildAdded:Connect(function()
	for _, parts in pairs(MainFol:GetChildren()) do
		if parts:IsA("BasePart") then
			if parts:FindFirstChild("") -- put the name of the 'BoolValue' here
				parts.Touched:Connect(onTouch)
			end
		end
	end
end)

I don’t have enough experience with CollectionService, so I won’t be able to give an example for that.

2 Likes

The first method half works, an issue arises when it tries to disable the particle emitter of the part. How would I locate the part thats being touched so I can specifically disable that part’s emitter?

Is there a ParticleEmitter for specific parts or all of the parts? Either way, you can simply make an if statement under the onTouch function checking if a ParticleEmitter exists before running the code that enables/disables the ParticleEmitter.

Also I just realized that I haven’t changed the code for the onTouch function, which is likely why you came across this issue.

Code for onTouch function:

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChild('Humanoid')

	if humanoid then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if player and canGet then
			canGet = false
			player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value = player.PlayerGui.Quest.ScoreBarFrame.TrainingAmount.AmountValue.Value + 1
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = false
			end
			otherPart.Transparency = 1
			task.wait(2)
			if otherPart:FindFirstChild("ParticleEmitter") then
				otherPart.ParticleEmitter.Enabled = true
			end
			otherPart.Transparency = 0
			canGet = true
		end
	end
end

I will use this same code in my previous post above

This works for what I’m doing, thanks!

1 Like

You are welcome, happy to help!
Also, in my previous post above, I forgot to change the script.Parent to otherPart.Parent, which I have just edited to now. I have also made the edit on the codes I have given in my other post above your post about the ParticleEmitter issue.

And I believe you should mark that post as the solution, as it explains a lot about how you can implement what you were trying to achieve. It can help others who may have a similar issue. (If you are wondering what post I’m talking about, it’s this post: Interacting with parts on client - #7 by BabyNinjaTime)

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.