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!
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.