Search code examples
luaroblox

invalid argument #3 (Instance expected, got string)


I was looking for a solution of this issue in search engines, but can't find one.

Though there's one that is almost identical, which is 'Invalid Argument #2 (String Expected, got Instance)', I tried looking ways to fix it in reverse, but it uses tostring(), and my issue is about the newest feature: Instance Attributes, which it doesn't support Instances as value, and the only thing I could do is to convert it as a string, now that the issue is about the Part.Parent, which uses Adornee/Instance or something on which I don't know the workaround for this

local LocalPlayer   =   Players.LocalPlayer;
local Mouse         =   LocalPlayer:GetMouse();

local function Part_Hide()
    if (Toggle_MouseHover == true and Mouse.Target ~= nil) then
        if (ReplicatedStorage:FindFirstChild("[Part_Storage]") == nil) then
            local Model         =   Instance.new ("Model", ReplicatedStorage);
            Model.Name          =   "[Part_Storage]";
            --Mouse.Target:SetAttribute("Source", Mouse.Target:GetFullName())
            Mouse.Target:SetAttribute("Source", Mouse.Target.Name)
            Mouse.Target.Parent =   Model;
        else
            local Model         =   ReplicatedStorage:FindFirstChild("[Part_Storage]");
            --Mouse.Target:SetAttribute("Source", Mouse.Target:GetFullName())
            Mouse.Target:SetAttribute("Source", Mouse.Target.Name)
            Mouse.Target.Parent =   Model;
        end
    end
end

local function Part_Unhide()
    if (ReplicatedStorage:FindFirstChild("[Part_Storage]") ~= nil) then
        local Storage   =   ReplicatedStorage:FindFirstChild("[Part_Storage]");
        for _, Child in pairs (Storage:GetChildren()) do
            --local Source  =   Child:GetAttribute("Source");
            --Child.Parent  =   Source
            Child.Parent    =   Child:GetAttribute("Source");   --  <-- Cause of the issue
        end
    end
end

I don't know if there's a way for an Attribute to accept Instances as value

Child.Parent = Child:GetAttribute("Source");

Is there a way to either convert String into an Instance, or an alternative way of saving an Instance as a value, or any kinds of workarounds for this issue? If so, answers are appreciated, thanks in advance!


Solution

  • As you've pointed out, Instances aren't acceptable as an Attribute type.

    One workaround might be to create an ObjectValue instead, and use that to hold onto the Instance reference. You can stuff it into the object before moving it over to ReplicatedStorage, and then just delete it when you pull it out of storage.

    local LocalPlayer = Players.LocalPlayer
    local Mouse = LocalPlayer:GetMouse()
    
    -- if the container for part storage doesn't exist, create it
    local PartStorage = ReplicatedStorage:FindFirstChild("[Part_Storage]")
    if (PartStorage == nil) then
        PartStorage = Instance.new("Model", ReplicatedStorage)
        PartStorage.Name = "[Part_Storage]"
    end
    
    local function Part_Hide()
        if (Toggle_MouseHover == true and Mouse.Target ~= nil) then
            -- alias the Mouse Target
            local Part = Mouse.Target
            local PartSource = Part.Parent
    
            -- move the part to storage
            Part.Parent = PartStorage
    
            -- hold onto the reference to where this object came from
            local ParentRef = Instance.new("ObjectValue")
            ParentRef.Value = PartSource
            ParentRef.Name = "ParentRef"
            ParentRef.Parent = Part
        end
    end
    
    local function Part_Unhide()
        -- move all parts out of storage
        for _, Child in pairs (PartStorage:GetChildren()) do
            -- remove the ObjectValue from the child
            local PartSource = Child:FindFirstChild("ParentRef")
            PartSource.Parent = nil
    
            -- place the child back into the world
            Child.Parent = PartSource.Value
    
            -- clean up
            PartSource:Destroy()
        end
    end
    

    As a small note, unless this is intended, you shouldn't do these kinds of world changing operations in a LocalScript, as those changes will only show up for the player that owns the LocalScript. The changes will be replicated to all players if you perform the work in a serverside Script.