How to get an instance's index in explorer (with script)?

well then I guess explorer changes order when you play, never tested that before so idk

because ipairs should work completely fine

Try this:

local Instance = 
for i = 1,#Instance:GetChildren() do
    print(i, Instance:GetChildren()[i])
end

image
image

It is something unnecessary because Studio orders them alphabetically

it’s still in wrong order
output:
image

explorer:
image

Well … it was another way, but it doesn’t matter, when testing the game it will always be ordered alphabetically. You could sort by letters and then place the original name.

It seemed to work fine, try re adding your objects but it might be because of how roblox sorts objects in the explorer.

Edit: Nevermind it worked because my object names was ordered correctly.

374x144, 50% 238x102, 71%

But I’m working with a plugin, so the objects are not sorted in that order.

You can’t make it sort, period. No scripting can make it sort. Better fix your plugin framework. If you are indexing it because of instance consider using FindFirstcChildWhichIsA("InstanceName").

1 Like

I’m pretty sure stuff like getchildren sorting is sorted by when the object was added. I don’t really get what your doing here, if your trying to sort things like an explorer or something else.

local objects = object:GetChildren()

table.sort(objects, function(object1, object2)
    return object1.Name < object2.Name
end)

print(objects) --[[
{
[1] = Script,
[2] = strVal,
[3] = boolVal,
[4] = RemoteEvent
}
]]

So it turns out you kind of can do this? but there are probably better solutions to your problem. In Roblox studio’s file directory there is a ReflectionMetadata XML file, that contains the metadata for (all?) instances and enums. Items/Instances in that file that show up in the explorer have an ExplorerOrder number property. It represents the sort priority of instances, thus using that you can figure out an instance’s order in the explorer. Here’s a dump of what should be all those values:

Dump
return {
	["Accessory"] = 30,
	["Accoutrement"] = 20,
	["AlignOrientation"] = 30,
	["AlignPosition"] = 30,
	["AngularVelocity"] = 30,
	["Animation"] = 220,
	["AnimationController"] = 220,
	["AnimationTrack"] = 220,
	["ArcHandles"] = 200,
	["Atmosphere"] = 5,
	["Attachment"] = 30,
	["Backpack"] = 30,
	["BackpackItem"] = 20,
	["BallSocketConstraint"] = 30,
	["BasePart"] = 3,
	["Beam"] = 30,
	["BillboardGui"] = 140,
	["BindableEvent"] = 50,
	["BindableFunction"] = 40,
	["BlockMesh"] = 30,
	["BloomEffect"] = 20,
	["BlurEffect"] = 20,
	["BodyAngularVelocity"] = 140,
	["BodyColors"] = 20,
	["BodyForce"] = 140,
	["BodyGyro"] = 140,
	["BodyPosition"] = 140,
	["BodyThrust"] = 140,
	["BodyVelocity"] = 140,
	["Bone"] = 30,
	["BoolValue"] = 30,
	["BoxHandleAdornment"] = 205,
	["BrickColorValue"] = 30,
	["CFrameValue"] = 30,
	["Camera"] = 5,
	["CharacterMesh"] = 220,
	["Chat"] = 510,
	["ChatService"] = 510,
	["ChorusSoundEffect"] = 20,
	["ClickDetector"] = 30,
	["Clothing"] = 20,
	["Clouds"] = 5,
	["Color3Value"] = 30,
	["ColorCorrectionEffect"] = 20,
	["CompressorSoundEffect"] = 20,
	["ConeHandleAdornment"] = 205,
	["Configuration"] = 220,
	["Constraint"] = 30,
	["CoreGui"] = 30,
	["CorePackages"] = 30,
	["CornerWedgePart"] = 120,
	["CustomEvent"] = 30,
	["CustomEventReceiver"] = 30,
	["CylinderHandleAdornment"] = 205,
	["CylinderMesh"] = 30,
	["CylindricalConstraint"] = 30,
	["DebugSettings"] = 20,
	["Decal"] = 40,
	["DepthOfFieldEffect"] = 20,
	["Dialog"] = 220,
	["DialogChoice"] = 220,
	["DistortionSoundEffect"] = 20,
	["DoubleConstrainedValue"] = 30,
	["EchoSoundEffect"] = 20,
	["EqualizerSoundEffect"] = 20,
	["Explosion"] = 30,
	["Feature"] = 20,
	["Fire"] = 30,
	["Flag"] = 30,
	["FlagStand"] = 30,
	["FlangeSoundEffect"] = 20,
	["FloorWire"] = 30,
	["Folder"] = 10,
	["ForceField"] = 30,
	["Frame"] = 150,
	["FunctionalTest"] = 10,
	["GameSettings"] = 20,
	["GlobalDataStore"] = -1,
	["GlobalSettings"] = 20,
	["GuiButton"] = 160,
	["GuiMain"] = 140,
	["Handles"] = 190,
	["Hat"] = 30,
	["HingeConstraint"] = 30,
	["Hint"] = 110,
	["Hole"] = 20,
	["Hopper"] = 20,
	["HopperBin"] = 240,
	["Humanoid"] = 30,
	["HumanoidDescription"] = 22,
	["ImageButton"] = 160,
	["ImageHandleAdornment"] = 205,
	["ImageLabel"] = 180,
	["IntConstrainedValue"] = 30,
	["IntValue"] = 30,
	["Item"] = 20,
	["JointInstance"] = 200,
	["Keyframe"] = 220,
	["KeyframeMarker"] = 220,
	["Light"] = 30,
	["Lighting"] = 30,
	["LineForce"] = 30,
	["LineHandleAdornment"] = 205,
	["LocalScript"] = 40,
	["LocalizationService"] = 530,
	["LocalizationTable"] = 30,
	["MeshPart"] = 105,
	["Message"] = 110,
	["Model"] = 100,
	["ModuleScript"] = 50,
	["Motor"] = 20,
	["Motor6D"] = 200,
	["NegateOperation"] = 104,
	["NetworkClient"] = 30,
	["NetworkReplicator"] = 30,
	["NetworkServer"] = 30,
	["NetworkSettings"] = 20,
	["NoCollisionConstraint"] = 30,
	["NumberPose"] = 220,
	["NumberValue"] = 30,
	["ObjectValue"] = 30,
	["OrderedDataStore"] = -1,
	["PackageLink"] = 1,
	["Pants"] = 20,
	["ParallelRampPart"] = 120,
	["Part"] = 110,
	["PartPairLasso"] = 220,
	["ParticleEmitter"] = 30,
	["PitchShiftSoundEffect"] = 20,
	["Platform"] = 30,
	["Player"] = 10,
	["PlayerGui"] = 130,
	["PlayerScripts"] = 130,
	["Players"] = 20,
	["Plugin"] = 30,
	["PluginDebugService"] = 30,
	["PluginGuiService"] = 30,
	["PointLight"] = 30,
	["Pose"] = 220,
	["PoseBase"] = 220,
	["PrismPart"] = 120,
	["PrismaticConstraint"] = 30,
	["ProximityPrompt"] = 30,
	["PyramidPart"] = 120,
	["RayValue"] = 30,
	["RemoteEvent"] = 50,
	["RemoteFunction"] = 40,
	["RenderSettings"] = 20,
	["RenderingTest"] = 40,
	["ReplicatedFirst"] = 30,
	["ReplicatedScriptService"] = 30,
	["ReplicatedStorage"] = 30,
	["ReverbSoundEffect"] = 20,
	["RightAngleRampPart"] = 120,
	["RobloxPluginGuiService"] = 30,
	["RocketPropulsion"] = 140,
	["RodConstraint"] = 30,
	["RopeConstraint"] = 30,
	["ScreenGui"] = 140,
	["Script"] = 30,
	["ScrollingFrame"] = 150,
	["Seat"] = 30,
	["SelectionBox"] = 210,
	["SelectionPartLasso"] = 220,
	["SelectionPointLasso"] = 220,
	["SelectionSphere"] = 210,
	["ServerScriptService"] = 30,
	["ServerStorage"] = 30,
	["Shirt"] = 20,
	["ShirtGraphic"] = 20,
	["SkateboardPlatform"] = 30,
	["Skin"] = 20,
	["Sky"] = 5,
	["SlidingBallConstraint"] = 30,
	["Smoke"] = 30,
	["Snap"] = 200,
	["Sound"] = 10,
	["SoundGroup"] = 20,
	["SoundService"] = 500,
	["Sparkles"] = 30,
	["SpawnLocation"] = 30,
	["Speaker"] = 10,
	["SpecialMesh"] = 30,
	["SphereHandleAdornment"] = 205,
	["SpotLight"] = 30,
	["SpringConstraint"] = 30,
	["StandalonePluginScripts"] = 130,
	["StarterCharacterScripts"] = 130,
	["StarterGear"] = 30,
	["StarterGui"] = 30,
	["StarterPack"] = 30,
	["StarterPlayer"] = 30,
	["StarterPlayerScripts"] = 130,
	["Status"] = 100,
	["StockSound"] = -1,
	["StringValue"] = 30,
	["SunRaysEffect"] = 20,
	["SurfaceAppearance"] = 40,
	["SurfaceGui"] = 140,
	["SurfaceLight"] = 30,
	["SurfaceSelection"] = 210,
	["Team"] = 10,
	["Teams"] = 140,
	["Terrain"] = 5,
	["TerrainRegion"] = 20,
	["TestService"] = 1000,
	["TextBox"] = 170,
	["TextButton"] = 170,
	["TextLabel"] = 190,
	["Texture"] = 40,
	["Tool"] = 30,
	["Torque"] = 30,
	["TorsionSpringConstraint"] = 30,
	["TouchTransmitter"] = 30,
	["Trail"] = 30,
	["TremoloSoundEffect"] = 20,
	["TrussPart"] = 120,
	["UIAspectRatioConstraint"] = 30,
	["UICorner"] = 30,
	["UIGradient"] = 30,
	["UIGridLayout"] = 30,
	["UIListLayout"] = 30,
	["UIPadding"] = 30,
	["UIPageLayout"] = 30,
	["UIScale"] = 30,
	["UISizeConstraint"] = 30,
	["UIStroke"] = 30,
	["UITableLayout"] = 30,
	["UITextSizeConstraint"] = 30,
	["UnionOperation"] = 105,
	["UniversalConstraint"] = 30,
	["ValueBase"] = 30,
	["Vector3Value"] = 30,
	["VectorForce"] = 30,
	["VehicleSeat"] = 30,
	["VideoFrame"] = 18,
	["ViewportFrame"] = 30,
	["VoiceSource"] = 10,
	["WedgePart"] = 120,
	["Weld"] = 200,
	["WeldConstraint"] = 30,
	["Workspace"] = 5,
	["WorldModel"] = 22,
	["WrapLayer"] = 32,
	["WrapTarget"] = 32
}

Now you can use :GetChildren() and sort by ExplorerOrder but also alphabetically. Because some instances have the same sort order, There are really two things that need to be handled, the first is simply sorting based on SortOrder and the other is if the sort orders are the same, sorting alphabetically.

local SortOrders = require(ExplorerOrders)

local function GetChildren(Instance)
	local Children = Instance:GetChildren()

	table.sort(Children, function(a, b)
		local a_Sortorder = SortOrders[a.ClassName]
		local b_Sortorder = SortOrders[b.ClassName]
		
		if a_Sortorder == b_Sortorder then
			return a.Name < b.Name
		else
			return a_Sortorder < b_Sortorder
		end
	end)

	return Children
end

Example Usage
--[[  

hierarchy

-> testpart
-> -> Script
-> -> boolVal
-> -> strVal
-> -> RemoteEvent

--]]

local OrderedChildren = GetChildren(game.Workspace.testpart)

print(OrderedChildren) --[[  
{
	[1] = Script,
	[2] = boolVal,
	[3] = strVal,
	[4] = RemoteEvent
}
--]]

local GetChildren = game.Workspace.testpart:GetChildren()

print(GetChildren) --[[  
{
	[1] = Script,
	[2] = strVal,
	[3] = RemoteEvent,
	[4] = boolVal
}
--]]

The reason I said “kind of”, is that using this function would only theoretically provide you with information on what the order should be not necessarily what it currently is. In better words, for example, if you were to rename an instance the hierarchy might not always reflect what this function will give you and that’s because studio doesn’t currently re-sort the hierarchy when you rename something. I do not know how your plugin will work, but in some cases you might be able to fix this by forcing a re-ordering through re-parenting:

local function force_sort(Instance)
	local temp = Instance.Parent
	Instance.Parent = nil
	Instance.Parent = temp
end
Example Usage
local Selection = game:GetService("Selection") --plugins only!

force_sort(game.Workspace.testpart)
local OrderedChildren = GetChildren(game.Workspace.testpart)

for i ,v in ipairs(OrderedChildren) do
	wait(1)
	Selection:Set({v})
end

but, you would have to do this everytime something is renamed, which could have really bad overhead. Optionally the better solution, if you know the initial order and if your plugin allows, is to compensate (remember/cache the order).

However, imo in general this is kind of hacky and creates a dependency on something that could easily change.


Edit: This may or not be issue for what you are doing but it would seem this doesn’t handle conflicting names very well, I’m not sure how instances are sorted in the explorer when names are the same.

2 Likes

Wow! Thanks for the information!
I didn’t know any of these things before! But the problem is

Nevermind! I’ll figure out some other way to do this. I really appreciate the effort you put into your reply!

TYSM

roblox explorer is indexed from their names like their first characters from CBA to ABC