How to loop through instance's property

Hello! I want an easy way to save parts to datastore. I read all about serializing parts but they are too complicated. So if there is a way to loop through an instance’s properties it would be so much more easier to save models. Because I want to save the player’s character’s model every time they join. If their character is already saved then I won’t do anything. The point is so that they can switch their avatar easily in the game. So does anyone know how to loop through and instance’s properties? Please help I know you are reading this thanks :slight_smile:

What exactly do you need to save?

I’m not really sure what you mean when you say save their character.

You could have a structure that looks like the following:

local toSave = {}

toSave.rightArm = {Transparency = someValue, Color = someColor, Size = someSize}
1 Like

I didn’t create this for nothing.

Thank you so much, but do you have a code that loops through a player’s character and saves it into a dictionary of some sort? I want to use datastore with it. Thank you!

I’m not going to be available for the night (in my time). I believe a dictionary will not be possible since name collisions could happen.

Furthermore, I suggest you look at the Usage section of the topic, and then you try to implement your approach.

I was able to implement this functionality using recursion. You can generate a structure that can reverse-engineered back to an Instance. It uses pcall because properties can be tagged as NotReplicated, which could throw up an error. But why not blacklist the tag? Because this may cause unexpected behavior, where the Instance still has some missing properties to be set.

local RPI = require(7309570414).new();
local Classes = RPI:getClasses();

local function safeIndex(t, k)
	local _, v = pcall(function()
		return t[k];
	end)
	
	return v;
end

local function generateHierarchy(Instance)
	local Hierarchy = {
		Name = Instance.Name;
		ClassName = Instance.ClassName;
		Children = {};
		Properties = {};
	};
	
	local Class = Classes[Instance.ClassName];
	
	for _, Property in pairs(Class:getMembers({"Property"}, true, false, {"ReadOnly", "NotScriptable"})) do
		Hierarchy.Properties[Property.Name] = safeIndex(Instance, Property.Name);
	end
	
	for _, Child in ipairs(Instance:GetChildren()) do
		table.insert(Hierarchy.Children, generateHierarchy(Child));
	end
	
	return Hierarchy;
end

local function generateInstance(Hierarchy)
	local Class = Classes[Hierarchy.ClassName];
	local Instance = Class:new();
	
	if (not (Instance)) then
		return nil;
	end	
	
	for propertyName, propertyValue in pairs(Hierarchy.Properties) do
		Instance[propertyName] = propertyValue;
	end
	
	for _, Child in ipairs(Hierarchy.Children) do
		Child = generateInstance(Child);
		
		if (Child) then
			Child.Parent = Instance;
		end
	end
	
	return Instance;
end

There are some exceptions as well. Certain Instances are tagged as NotCreatable, which is pretty self-explanatory.

Usage

With the code above appended, we can run generateHierarchy to save an Instance, and generateInstance to create it.

local myInstance = generateHierarchy(workspace.Baseplate);
...
generateInstance(myInstance).Parent = workspace; -- may give nil if Instance is NotCreatable

Hope this helps.

P.S. It seems this will not work with characters since they are mostly composed of MeshParts, which have their MeshId locked to Scripts. Still keeping this here though.