LocalScripts stop working after SurfaceGui assigned to same adornee twice #RobloxDev

So here’s the problem I found (solution below, too 🙂 )

I have trees in Battle Farm that are managed through a series of SurfaceGuis (with buttons to plant, cut down, etc). The Guis are in the player.PlayerGui (since the buttons use LocalScripts) and assigned an Adornee called “Readout”, which is an invisible brick wrapped around the tree trunk:

When there is no tree planted in the spot, that SAME Readout brick has a SurfaceGui that says “Click to Plant”:

And when I first load each tree, they work fine.

HOWEVER – if you

  1. Click to plant a tree (GUI 1)
  2. THEN click the “water” button ON THAT SAME TREE (GUI 2)  after it’s planted,
  3. Nothing happens. In a gui that if loaded first (loading a planted tree) works fine.

I tried a lot of things:

  1. Deleting any SurfaceGuis from player.PlayerGui with the Readout assigned as Adornee using Destroy()
  2. Trying the same but using game.Debris:AddItem(gui,0)
  3. Testing for script Disabled, Zindex, etc etc

Ultimately, here’s what worked:

Before swapping out the GUI, I first cloned the readout part, destroyed the old readout part and assigned the GUI to the new (identical) readout part. Lots of extra overhead but it was the only way I could find to fix it.

function tycooncontrol.applyDecalToTreeReadout(player, orig_readout_part, planted_or_unplanted)
	-- first we're going to try deleting and redoing the readout part
	for _, gui in pairs(player.PlayerGui:GetChildren()) do
		if gui.ClassName == "SurfaceGui" and gui.Adornee == orig_readout_part then
			gui:Destroy() -- destoying any guis attached to the current readout part
		end
	end
	orig_readout_part.CanCollide = false
	local readout_part = orig_readout_part:Clone()
	readout_part.Parent = orig_readout_part.Parent
	orig_readout_part:Destroy()

When your SurfaceGui isn’t showing up on its adornee #RobloxDev

So this might be a problem only I have because I am a weirdo but … just in case.
I was running a script where I:

  1. Cloned a model
  2. Passed the cloned model through to a function to do some stuff to it, including:
  3. Cloned a SurfaceGui
  4. Assigned the SurfaceGui parent to the PlayerGui
  5. Set the SurfaceGui Adornee to one of the pieces in my cloned model
  6. Parented the model in the workspace

The problem was, my GUI was not showing on the model. The cloned gui was in my player.PlayerGui, and the Adornee was assigned, but it was invisible.
I checked if it was enabled, I checked if all the elements were visible .. nothing.
And then I realized that the model’s parent was set AFTER the adornee was being assigned to the part in the model.
When I gave the model a parent in the workspace and THEN assigned the Adornee, all was well. I am left to assume I shouldn’t be assigning adornees in models outside the workspace.

So: if you’re assigning a SurfaceGui adornee to a model without a parent, try parenting the model first.