You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Instances of scenes with a Material flagged Local to Scene see their material instances become independent and change ID every time you reopen the scene containing them
#77997
Closed
hsandt opened this issue
Jun 8, 2023
· 3 comments
· Fixed by #65011
Local to Scene is convenient for Materials because when changing properties / shader parameters by code, we often want to affect a single entity, not all of them.
However, when the material is placed on a scene to be instantiated (aka "prefab", "blueprint" or "archetype" in other engines; we'll call it "model scene" below), and flagged Local to Scene, each instance has the two following behaviors:
Independent: They create their own embedded material instance. While it seems to follow Local to Scene's design, this means such instances will stop being updated with new changes on the original material on the model scene. In addition, the Local to Scene tooltip says that it should affect run-time, not edit time. Although there is a point in making some changes in edit time (namely ungreying the fields to allow user to change some instance fields in the inspector to override defaults), this seems to go too far by breaking the original resource relationship.
ID change: Every time the scene containing the instances is closed and reopen, the material ID will change in both the SubResource declaration and reference, polluting VCS diff.
Saving the material as an asset (Resource) instead of being embed in the model scene doesn't fix the issue.
For now, my workaround is to manually duplicate the resource to make it a unique instance at runtime, on game start (or node instantiation), as I do in other engines:
sprite.material = sprite.material.duplicate()
This doesn't allow overriding property instances in the inspector at edit time, but at east it avoids sharing material shader parameter updates with all instances (whether due to scene instantiation or material resource asset reuse), while avoiding the repeated ID change.
Steps to reproduce
The best is to download the MRP and read the Git history which explains each step and shows the diff. It also has additional steps to demonstrate cases where the bug does not occur. Below, I'll sum-up the core steps:
ID change
Create a scene with a sprite with a CanvasItemMaterial flagged Local to Scene
Create another scene where you instantiate the model scene
Save the new scene and commit in Git.
Close and reopen the scene and observe the diff
Observed diff:
CanvasItemMaterial ID changes in both sub-resource declaration, and reference usage.
Since the ID change can be repeated indefinitely, you can also open the MRP and repeat step 4 as many times as you want. Note that the MRP has 2 scene model instances so you will see 2 IDs changing each time.
Independence
Change some property on the model scene material such as particles_animation = true
Save model scene, open scene with instance and save: particles_animation is not updated on the instance
Bonus: Material as Resource
Save material as a resource asset and try again: the bug still occurs.
This is true not only for Material, but also for resources that enable resource_local_to_scene.
Resource only needs to be located on the root node of the sub-scene. When the main scene is reopened and saved again, the ID of the resource in the tscn file of the main scene will continue to change.
When packing the scene, the ID is determined according to the instance, and when the scene is instantiated, the new instance of the resource is a copy of the record. When instantiating a scene, a new copy is created, which also needs to copy the id information recorded in the scene file.
Ah, so THAT's what's causing it. I have some animated sprite materials for projectiles, so each instance needs to animate independently, so they need to be local to scene. However, the scene that contains the mesh keeps overwriting the reference to the material resource with its own local copy. I keep having to revert it.
Actually, I think I knew that and my memory is terrible. Wonder if there's another issue open about this.
Godot version
v4.0.2.stable.official [7a0977c]
System information
Linux Ubuntu 22.04 with Unity desktop
Issue description
Local to Scene is convenient for Materials because when changing properties / shader parameters by code, we often want to affect a single entity, not all of them.
However, when the material is placed on a scene to be instantiated (aka "prefab", "blueprint" or "archetype" in other engines; we'll call it "model scene" below), and flagged Local to Scene, each instance has the two following behaviors:
Saving the material as an asset (Resource) instead of being embed in the model scene doesn't fix the issue.
For now, my workaround is to manually duplicate the resource to make it a unique instance at runtime, on game start (or node instantiation), as I do in other engines:
sprite.material = sprite.material.duplicate()
This doesn't allow overriding property instances in the inspector at edit time, but at east it avoids sharing material shader parameter updates with all instances (whether due to scene instantiation or material resource asset reuse), while avoiding the repeated ID change.
Steps to reproduce
The best is to download the MRP and read the Git history which explains each step and shows the diff. It also has additional steps to demonstrate cases where the bug does not occur. Below, I'll sum-up the core steps:
ID change
Observed diff:
CanvasItemMaterial ID changes in both sub-resource declaration, and reference usage.
Since the ID change can be repeated indefinitely, you can also open the MRP and repeat step 4 as many times as you want. Note that the MRP has 2 scene model instances so you will see 2 IDs changing each time.
Independence
particles_animation = true
Bonus: Material as Resource
Save material as a resource asset and try again: the bug still occurs.
Minimal reproduction project
v4.0.2 - Material of instance of scene with Local to Scene material keeps changing ID.zip
The text was updated successfully, but these errors were encountered: