Cloning an Instance without cloning its children

I often find myself needing to clone an instance exactly without including children. I could temporarily remove the children or make them non-archivable, but this can inadvertently interact with other scripts and potentially mess with ChangeHistoryService when done from a plugin or the command bar.

Some use-cases:

  • Cloning multiple instances while maintaining instance references between them (e.g. ObjectValue.Value).
  • Cloning a part that has extra data (such as offset values) stored in it, without cloning unnecessary instances.

Here’s my current workaround. It works for most cases, but is extremely slow and impractical when cloning top-level instances with thousands of children:

local function CloneWithoutChildren(instance)
	local instance2 = instance:Clone()
	instance2:ClearAllChildren()
	return instance2
end

Another workaround could be to store property names in lists and clone the instance manually, but this is slower in some cases, and does not work on some instances including Scripts, MeshParts and Unions.

A solution to this problem could be implemented as a new :CloneWithoutChildren() method for instances.
Although unlikely, this may interfere with scripts that try to access children named “CloneWithoutChildren” (I personally always use :FindFirstChild for this reason)

local instance2 = instance:CloneWithoutChildren()

It could also be implemented as a new parameter for :Clone().
This would cut down on API bloat, but perhaps this parameter should be saved for a different feature (like ignoring .Archivable).

local instance2 = instance:Clone(true)
55 Likes

This would be a really useful addition to the studio tool set.
Roblox please give us this :slight_smile:

Just pointing this out, OP mentioned that already

This is being added soon as Instance.fromExisting(template: Instance).

  • It will not copy children

  • It will copy even if Archivable = false (this is such a frustrating edge case of Clone)

  • It will not let you copy things you shouldn’t be able to (like Players) :slight_smile:

Does still copying non-archivable things make sense? It feels appropriate for something called “fromExisting”.

15 Likes

The Archivable ignoring makes sense to me - I think it’s good that it’s ignored here. I’m not sure if the name adequately implies that children aren’t copied, but it’s not a bad name.

I would go more in the direction of newSimilarTo, or newAlike, or newFromProperties.

The new in my mind makes it clear that this is creating something new, and that this isn’t a perfect copy - you’re not copying children after all. I think it’d still reasonably indicate that the new instance is modelled after the properties of the existing instance though.

newFromExisting is maybe acceptable? It kind of feels like it doesn’t properly set up the expectation that the new instance only resembles the template rather than being a full clone with descendants.

Type.fromXXX is the standard pattern for non-default constructors among all of the data types. Do you not think it’s clear enough that it is constructing something new simply by following that pattern?

2 Likes

I think it’s clear that it’s constructing something new, but I’m not sure if it really emphasises that it’s more like constructing a new thing in comparison to behaving like a full clone.

I suppose then, to modify my suggestions, fromSimilar, fromAlike, fromProperties, etc. Something that indicates a resemblance without being quite as easily confused with identical-ness.

To be clear, your suggested name isn’t bad at this, but I think there’s a chance it could be better.

I feel like “fromInstance” moreso communicates that it’s not copying children and is concerned only with the specific instance. This is a challenging name.

3 Likes

Would it make more sense to just let Instance.new() also take an instance instead of a string?

2 Likes

I agree. It’s a bit counter-intuitive. I think the ones OP suggested in the title would be more fitting, but there’s probably special reason why they chose to add it onto Instance

1 Like

Point of new is that it creates an Instance from the bottom. Instance.fromExisting sounds clear that you’re creating a (new) Instance from an existing Instance (heck, aren’t there constructors with similar naming anyway, like CFrame.fromEulerAngles). Besides, @Elttob, what would fromProperties mean? Can’t construct an Instance solely from Properties, that’s what its name refers to.

I think it’s not necessary whatsoever to modify the default constructor.