Trigger proximityPrompt with custom GUI inside a mesh

Hi,

I’m trying to make a custom proximity prompt that shows a BillboardGui and triggers a Highlight. It works fine using a LocalScript in StarterPlayerScripts, but doing this for every mesh feels like it will lag my game.

I want each mesh to handle its own prompt and gui, but LocalScripts don’t really run in Workspace and regular Scripts can’t handle client-side stuff like GUI or highlights. What’s the least laggy/cleanest way to handle this per mesh without overcomplicating things?

Appreciate any help! :slight_smile:

Localscript in StarterPlayerScript:

local camera = workspace.Art_Class:WaitForChild("Camera")
local prompt = camera:WaitForChild("ProximityPrompt")
local gui = camera:WaitForChild("Mesh_Prompt")
local highlight = camera:WaitForChild("Highlight")
local actionText = gui:WaitForChild("ActionText")
local keyInput = gui:WaitForChild("KeyInput")

local textures = {
	camera:WaitForChild("TextureFront"),
	camera:WaitForChild("TextureBack"),
	camera:WaitForChild("TextureLeft"),
	camera:WaitForChild("TextureRight"),
	camera:WaitForChild("TextureTop"),
	camera:WaitForChild("TextureBottom"),
}

local animating = false

local function animateTextures()
	while animating do
		for _, texture in ipairs(textures) do
			local offset = math.random()
			texture.OffsetStudsU = offset
			texture.OffsetStudsV = offset
		end
		wait(0.1)
	end
end

highlight.Enabled = false
gui.Enabled = false
for _, texture in ipairs(textures) do
	texture.Transparency = 1
end

prompt.PromptShown:Connect(function()
	highlight.Enabled = true
	gui.Enabled = true
	highlight.OutlineTransparency = 0
	actionText.Text = actionText.Text

	for _, texture in ipairs(textures) do
		texture.Transparency = 0.5
	end

	animating = true
	task.spawn(animateTextures)
end)

prompt.PromptHidden:Connect(function()
	highlight.Enabled = false
	gui.Enabled = false
	highlight.OutlineTransparency = 1

	for _, texture in ipairs(textures) do
		texture.Transparency = 1
	end

	animating = false
end)

keyInput.MouseButton1Click:Connect(function()
	prompt:InputBegan(game.Players.LocalPlayer)
end)

prompt.Triggered:Connect(function(player)
	print("it works!")
end)

You can do a for loop and put the script into the StarterPlayerScripts

local CollectionService = game:GetService("CollectionService") -- Allows for tags

for _, mesh in workspace:GetChildren()
 if CollectionService:HasTag(mesh, "Interactable") then
  -- put your code here (function ?)
 end
end)

Just make sure your meshes that you want to interact with have the interactable tag to them. This can be found under the mesh’s properties all the way at the bottom i believe.