-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Duplicating a node should result in either a true Instance or true unique copy, not a mix of both #317
Comments
Setting up resources to be unique across instances is possible by enabling It works for scenes only though. I wish I knew about this feature from the moment I started using Godot! Resources are shared by default to improve re-usability and performance. Scripts are also resources and they 99% of the time have to be shared. One can take a conscious advantage of this so that changes to a single resource can affect some behavior of existing nodes at run-time so you don't have to go through each node to change a particular property (say friction, see PhysicsMaterial). I think there's much confusion as to how duplicating works in Godot, for instance see godotengine/godot#33824. So yeah I think it's necessary to distinguish between shallow/deep/instance duplication across the editor. Adding an additional submenu popup for this could be a step forward: |
Related to @Xrayez's comment: godotengine/godot#6258, godotengine/godot#6922, godotengine/godot#9037 |
Thank you @Xrayez for sharing your thoughts! I totally get why it is good and important to allow resources to be shared. Or clearly differentiate between instancing (everything shared) and duplication (everything unique). The shapes resource is just a visual example you can easily miss until many many commits later. I actually have and had much more problems with scripts and animations before I learned never to share scripts and never to save animations. It should not be like that. Sharing scripts with nodes should not threat to override your work if you did not know about that checkbox or forgot to tick it. Neither should saving animations or changing CollisionShapes be a threat to the work you already created. |
I agree with the naming change. Duplicate doesn't suggest the linked copy. When I duplicate the file on computer it doesn't change because I change original or more importantly even original doesn't change because I edited a copy. Separating instance and duplicate would be clearer |
@Calinou I believe the |
If we implement this proposal, would that help with your issue? The workflow would be Duplicate Node -> Make Subresources Unique |
Duplicating a node merely duplicates its node tree. Perhaps it doesn't do what you expect it to with some idea on mind but, it does what it says it does and not more. This behavior should stay as is. When in the editor, I think you should consider making these nodes you duplicate a separate scene and instance them in the main scene. If needed, mark those particular resources that you want to make unique with "Make local to scene". If duplicating nodes in GDScript, you should consider again separate scenes instances and duplicating nodes with the DUPLICATE_USE_INSTANCING flag. |
My proposal #2737 keeps duplicating a node the same. I'm referring to the behaviour of Make Subresources Unique which only operates on 1 layer of subresources. I'm suggesting that Make Subresources Unique should truly make all the subresources unique. |
The important thing to understand is not that the software should do what it says it will do. You have to be in empathy with the user. Here is at least one use case that leads to say that ctrl + D should create unique instances :
In this process, you will have exactly duplicated nodes, but you want to have true differents instances because each tree can be configurable with for examples values in the editor. The user experience is the most important, not the pure logic of the software because it's used by human beings I'm not saying that this particular solution should be implemented, but at least we should have the possibility to easily duplicate an instance without making it linked to the original one. |
I find this post confusing because there are 5 ways it could be implemented and I'm having track of which methods are being called what.
I'd hope 1. would be called instancing because its what happens when we instance a packed scene. I'd expect duplicate to mean 4 |
I think you have to approach this more form "what a user wants and expects" rather than "how or why the system currently works as it does". I know how and why the system works the way it does, it just makes no sense from a user perspective. If I duplicate a body with a CollisionShape and change it's extends, I don't expect or want any other CollisionShape to change too, unless I explicitly told it to. This should be opt in, rather than opt out, as it currently is. |
I just had an idea: introduce more flags to the node.duplicate() 1 flag for how it treats resources marked local to scene (true duplicates them false doesn't) 1 flag for how it treats resources that are not marked local to scene (true duplicates them false doesn't) 1 flag for how to treat sub resources (recursive)marked local (true duplicates them false doesn't) 1 flag for how to treat sub resources (recursive) not marked local. We could have the same flags for instance() too. That way the user could define just about any behavior they want. Maybe even another flag for linking variables of the node such as canvas item like they were expecting but idk that might get weird because its not a resource so passing it by reference might not be possible in gdscript. There is already that DUPLICATE_USE_INSTANCING flag which sounds like what I just described but from my experiments its not. |
I did some mockups and feature suggestion here, if you want to take a look at it. I hope it helps for the debate ;p |
As a level designer, I cannot describe how often the current duplication behavior has been driving me crazy, especially since I do not know such behavior from any other 3D software. To give you a perspective on the importance of fixing this here is an example of how annoying this is:
Now when want to add such a zone, I often duplicate an existing one, since it is probably not far away in the viewport and has similar sizes. I then have to make three resources unique every time I make a new area. This is time-consuming. But the worst part is, that it is very easy to forget, and when the old area is not in view any more or hidden, there is no way of noticing, that you are overriding carefully placed colliders. Repeat this a few times and you can lose several minutes of work and feel very frustrated. This problem applies to a multitude of similar systems. I think for beginners, this behavior is particularly unintuitive and off-putting. One way of fixing this could also be to have a setting on a resource field, next to "Local to Scene" that would say "Make unique on duplication" or something like "Unique for instance" which would make sure that this resource is unique for every instance. Reading the solution from @lukostello, I want to mention that this might not only apply to objects that have been "Made local", but also for objects with "Editable children" applied. |
What is the current state of this proposal? Has it been accepted, or does it need more work to clarify what exactly will change and how that change will be implemented? I'm also being bitten by the fact that doing a deep copy isn't easily available. |
#4672 contains more recent discussion on the subject. (If you are looking into doing this from code, I assume #4672 will also expose a method/flag to do the same operation from code.) That said, you can see it's quite a controversial subject, so I wouldn't expect significant movement on this anytime soon. Feel free to open a pull request following #4672, but there's no guarantee it would be merged without significant changes. |
Controversial maybe, and much more about the solution to apply. But in the issue you linked, many people appears to agree on the fact that things are really confusing at the moment about shared ressources and the default behavior of copy paste of a node. |
For me, the expected behavior when using
Fortunately, Godot is very open, so my solution is this:
|
I still can't believe how many years that this issue has sat here; furthermore, I can't believe that, 'Duplicate,' makes a reference instead of a unique actual duplicate in the first place. Seems like an incredible oversight in design. 99% of the time the user is gonna want and expect a duplicate, not a reference. And the fact that the only alternative, seemingly at this time, to actually duplicating a node is manually recreating it is simply preposterous in my opinion |
@Malleator What is confusing, is that duplicate does make an actual duplicate, but only of the node itself, not of the Resources this node uses. So to not be completely confused and fucked by this issue, you first have to have a really good understanding of what Godot means by "Resource" and how this is different from the node. Nodes use Resources. Take a Sprite for example. When we see a graphic in a 2D game most people would call this a Sprite. When in fact what we see is a texture (= Resource) displayed by a Sprite Node. If the user duplicates this Sprite, Godot will create a new Sprite instance from the Sprite class and assign it the same Resource by reference. Meaning the user can change all Sprite properties individually for each Sprite, but as soon as the user fiddles with the Resource of one Sprite, all Sprites will suddenly adopt these changes. Now for a Sprite using a Texture resource this might be desired behaviour. For a CollisionShape using a Shape resource however, or an AnimationPlayer using an Animation resource, or a Node using a Script resource, ... this might not be desired in the most cases. The biggest problem Godot has in this regard imho, is the silence. The total lack of transparency and feedback in communicating this to the user via the Editor GUI. You basically have to be an expert Godot user to fully understand this behavior which is very specific to Godot. Would it be more transparent (for example with a giant icon and large fat text next to the resource in the Inspector making it crystal clear this resource is shared or unique, I think this issue would be much less of a problem. |
I understand your point of view, but imho your overcomplicate things. There are so many simple solutions and different level of answer for this user's needs. Level 0 : Explain to the customer in some way how it works when duplicating a node (resource will not be duplicated, but reference will be kept for each node). In fact, the issue here is not wether this user's need is relevant or not. Many people are convinced that this IS relevant (but not very critical maybe). It is only a question of wether a developer would like to make any of these modifications above or not, because this project is open source so I guess we just have to wait for a developer to make a small modification to answer this issue. |
I came across the same issue while duplicating nodes via code. Duplicating a parent node, especially one with exported variables, retains references from the original parent node, which I consider a bug. I've observed similar problems in other related issues here in GitHub, where users are confused, negatively impacting the user experience (UX) for some. Currently, I can only see a few practical uses using this behavior. In most software applications, duplicating something typically creates a unique copy. A potential solution could involve offering two options: "Duplicate as New" and "Duplicate (Use Original References)". This approach would not only help users understand the intended functionality, but also improve the overall UX (similar to the "Duplicate" and "Duplicate Link" function in Blender, but a little different in this case from what I understand). Edited: Additionally, duplicating a scene (.tscn) via the Scene Window, the same bug will happen, making it difficult for level designers, since the exported variables of the duplicated scene will reference the children of the previous scene duplicated. Edited Again: The same can happen even if it's a simple node, meaning its NOT only the .tscn; I think my issue here is with the exported variables. The reference of the path node will always reference the previous duplicated node for some reason. I don't think that is intended behaviour. I should probably open a new issue for this? |
As someone who is new to Godot, I just want to say I've lost many hours of work due to this. It is counter-intuitive to what I believe most new users will expect when they duplicate something. Although there are times when you want shared data between the two - you would never want a script duplicated on two nodes for example - I think the majority of the time the expected behaviour is that a duplication is completely seperate and changes to one wont affect the other. |
I think the biggest offender here is the user being betrayed by terminology. In any other situation when working with a computer, duplicating something with Ctrl + D(uplicate) creates an independent copy of whatever was duplicated. If I duplicate a document that references external images, I expect edition of font size in the copy to just happen there while those external images remain existing only once. If I duplicate a node tree I expect the resources it may reference to be shared, but not internal settings like bounding size to be entangled. Specially if they are like this silently with no indication about them being connected. Regardless of the debate about what should be the default, a non-independent copy umbilically connected to it's brothers should absolutely be called an INSTANCE, not a duplicate, and the context menus and even keyboard shortcuts should reflect this nuance. I too have lost work to this intuitiveness and sneaky undisclosed behavior behind my back. At the very least add a way to quickly make true unconnected duplicates of stuff If we are this dead set on having the main default way be secretly instances but enjoy the term "duplicate" |
I agree with what everyone else is saying. "Duplicate" does not imply "Instance", "Shared" - it implies a unique copy - because that's literally how everything else works. If we create copies of our applications in various states as forms of backup, we do not expect any changes we make to the current to be applied to the former backup. That is absurd. This isn't even about game engines, this is about consistency of expectation that is shared across multiple pieces of software going back as far as I can remember. In a DAW if I copy a piano roll and make edits to a single measure, I do not expect those changes to apply to previous piano rolls in earlier measures. No software does this. When you copy or duplicate it becomes its own unique entity. Imagine if Photoshop does this with layers, DAWs do this with edits, NLE's do this with video editing, effects, timeline - mass hysteria. A LOT of what Godot does changes the game for development in a good way but there's corners here and there that make absolutely no sense in any context you try to give it. An actual "duplicate" as everyone else understands because they've been making duplicates or copy/pasting across multiple pieces of software for decades is the expectation, the current behavior is not and does not improve the workflow in any way, it hinders it. |
same here, would it be possible to add a enum DuplicateFlags, to chose if a copy or copy of instance is duplicated ? |
Duplicating is a frequent operation, so I don't think it should spawn a dialog every time you try to duplicate something. At most, it should display a toast to mention a resource is shared when you duplicate it (specifically if we go for #4672). |
I ran into this problem today when working with UI. Users in the Godot Discord were also confused about how to fix it when I asked for help. I have a "button" scene with a script attached. The script assigns information to the button's labels based on other info in my project. I dragged the button scene into the node hierarchy, and then duplicated it twice. So, there was "button," "button2," and "button3." All three buttons should grab different information and assign it to themselves. On _ready(), my code for all three buttons ran, but applied everything to the labels of "button." Buttons "button2" and "button3" remained blank. This default behavior is extremely confusing. It led to me trying to debug my code, only to realize my code was fine. Echoing what others here have said, duplication or copy/pasting should not create a linked instance; it should create a unique copy, similar to just dragging the scene into the hierarchy multiple times (which fixed the issue for me. The buttons all grabbed their own information, as expected). Providing a separate button/shortcut for "Make Linked Instance" would alleviate a lot of confusion. |
Since making a new button to create an independent duplicate isn't a popular option |
Just ran into another issue that appears to be linked to this issue, with resources. I have two resource types - for simplicity, let's call them apple and pear. I had an apple in my file system, and I wanted to create a pear. So, I duplicated my apple resource, removed the "apple.gd" script, and added pear.gd. So now, functionally, from the end-user's perspective, it has been converted into a pear. Unfortunately, when I went to "quick load" the pear resource for an export in the inspector, it wouldn't show up. Only once I deleted the pear, created a new pear resource from scratch, and assigned pear.gd to it, did it finally show up in quick load. |
Hi all - Someone posted something about this on Reddit and I think the solution could be fairly simple:
I feel that if we havea default setting we're always going to be thinking about the "toggled off" option when working in the editor. That's it, fairly clean. Thoughts? |
What is the workaround while this is being argued? Do you have to just add each resource and re-do it? In my case my CollisionShape2D's all resize when I try to resize 1.. I just used duplicate as a shortcut, but do I just need to delete them all and re-add them each as new? |
To my knowledge, yes. In some instances duplicating will just create unique instances, which makes this even more confusing. In case you weren't aware, you can right click on components of a node and hit "make unique." For example, this will work with the mesh of a MeshInstance3D; make one, assign its shape, and duplicate the node. They'll be linked. Right click the second one's mesh and hit make unique. They'll no longer be linked. I'm not sure if there's an indication anywhere that they're linked. I'd like to be able to view that information, if it's there. |
@amarraff Thank you for clarifying! |
Describe the project you are working on:
In all my projects I'm duplicating and instancing nodes all the time.
Describe the problem or limitation you are having in your project:
When I duplicate nodes, they are neither unique (aka independent or disconnected from their original), nor are they completely connected: a pure instance where changing one thing in any one of the duplicates results in the same change happening to all of the duplicates.
Describe how this feature / enhancement will help you overcome this problem or limitation:
Having either true Instances of nodes or true unique duplicates would prevent confusion, unintentional changes, self inflicted bugs.
Ideally I would like to be able to do something like
If I would want a specific Resource to be shared, by multiple nodes, I would like to Save the resource as a .res for instance, and then load it into any another node (already possible).
This would be intentional driven design for me.
Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:
Imagine either both color changing and shapes changing in the gif above (true instance) or both color and shape changes stay independent from the original (unique duplicate)
Describe implementation detail for your proposal (in code), if possible:
for me not possible
If this enhancement will not be used often, can it be worked around with a few lines of script?:
Would be used a lot because duplication of nodes is a very common thing in Godot.
Is there a reason why this should be core and not an add-on in the asset library?:
It's about existing core functionality
The text was updated successfully, but these errors were encountered: