Skip to content
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

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

Comments

@hsandt
Copy link
Contributor

hsandt commented Jun 8, 2023

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:

  1. 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.
  2. 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

  1. Create a scene with a sprite with a CanvasItemMaterial flagged Local to Scene
  2. Create another scene where you instantiate the model scene
  3. Save the new scene and commit in Git.
  4. Close and reopen the scene and observe the diff

Observed diff:

image

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

  1. Change some property on the model scene material such as particles_animation = true
  2. 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.

Minimal reproduction project

v4.0.2 - Material of instance of scene with Local to Scene material keeps changing ID.zip

@Rindbee
Copy link
Contributor

Rindbee commented Jun 15, 2023

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.

@jitspoe
Copy link
Contributor

jitspoe commented Jul 27, 2023

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.

@akien-mga akien-mga added this to the 4.2 milestone Aug 7, 2023
@Koopa1018
Copy link

Oh nice the ID change problem is known! Thank goodness 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants