Quick answer: In Godot, exported resources are shared by reference between all instances of a scene by default. Modifying a resource property on one instance changes it for all instances. Use resource_local_to_scene or duplicate() to create unique copies.
Here is how to fix Godot resource sharing unintended state. You spawn three enemies from the same scene. You change one enemy’s health bar color to red. Suddenly all three enemies have red health bars. This is one of Godot’s most counterintuitive behaviors—resources are shared by reference between scene instances by default, and modifying one silently modifies them all.
The Symptom
You have a scene—say an enemy or a UI panel—that uses an exported Resource such as a StyleBoxFlat, a custom Resource script, or a ShaderMaterial. You instantiate multiple copies of this scene. When you change a property on the resource in one instance at runtime, the change appears on every other instance too.
# enemy.gd
extends CharacterBody2D
@export var stats: EnemyStats # Custom Resource
func take_damage(amount: int):
stats.current_hp -= amount # This changes HP for ALL enemies!
You expected each enemy to have its own HP pool. Instead, damaging one enemy damages all of them. The debugger shows that every instance’s stats property points to the exact same object in memory.
This behavior also manifests with built-in resources. A StyleBoxFlat assigned in the editor to a PanelContainer will be shared across all instances. Changing the background color of one panel changes it for every panel that uses the same resource.
What Causes This
Godot’s resource system is designed around sharing. When you assign a resource to an exported property in the editor, every instance of that scene receives a reference to the same Resource object. This is intentional and efficient—it means textures, meshes, and materials are loaded once in memory and shared across all nodes that use them.
The problem arises when you treat a shared resource as if it were unique to each instance. A Texture2D being shared is fine because you rarely modify textures at runtime. But a custom Resource that holds mutable game state—like enemy stats, inventory data, or UI styling—will cause cross-contamination when modified.
Godot does not create copies automatically because doing so would be wasteful for the majority of resources. A single material shared by 100 enemies is far more efficient than 100 duplicate materials. The engine trusts you to make copies when you need unique state.
The Fix
Option 1: Use resource_local_to_scene in the editor. This is the cleanest solution when you know at design time that a resource needs to be unique per instance. Select the resource in the Inspector, and enable the resource_local_to_scene checkbox. Godot will automatically duplicate the resource for every scene instance.
If you are creating the resource in code, set the property directly:
# In your custom resource script
class_name EnemyStats
extends Resource
@export var max_hp: int = 100
@export var current_hp: int = 100
@export var attack: int = 10
func _init():
resource_local_to_scene = true
Option 2: Call duplicate() in _ready(). This approach gives you explicit control. In the node script that holds the resource, create a unique copy at startup:
# enemy.gd
extends CharacterBody2D
@export var stats: EnemyStats
func _ready():
stats = stats.duplicate() # Now this instance has its own copy
func take_damage(amount: int):
stats.current_hp -= amount # Only affects this enemy
Option 3: Create resources in _ready() instead of exporting them. If every instance always needs unique state, skip the export entirely and construct the resource in code:
extends CharacterBody2D
var stats: EnemyStats
func _ready():
stats = EnemyStats.new()
stats.max_hp = 100
stats.current_hp = 100
stats.attack = 10
For StyleBox and Material resources attached to Control nodes, you can also right-click the resource in the Inspector and select Make Unique. This creates a one-off duplicate in the editor, but be aware this only applies to that specific scene instance in the editor—runtime-spawned instances will still share unless you use one of the code approaches above.
Why This Works
The resource_local_to_scene flag tells Godot’s scene instantiation system to call duplicate() on the resource automatically when a scene is instantiated. Each instance gets its own copy in memory, so modifying one does not affect the others. This is handled at the engine level during the instantiation process, which makes it both reliable and efficient.
Calling duplicate() manually achieves the same result but gives you control over when the copy happens. This is useful in situations where you want to share the resource initially (for memory efficiency) and only create a copy when you are about to modify it—a pattern sometimes called copy-on-write.
The key insight is that Godot’s default behavior is correct for the majority of use cases. Textures, fonts, meshes, and audio streams should be shared. It is only mutable state—resources you intend to modify at runtime—that needs to be duplicated. Once you internalize this distinction, the behavior stops feeling like a bug and starts feeling like a useful optimization you can opt out of when needed.
Related Issues
If your scenes fail to load in the first place, see Fix: Godot Packed Scene Instantiation Returning Null for how to debug load() and instantiate() failures.
If you are managing global game state through autoloads and running into access issues, check Fix: Godot Autoload/Singleton Not Accessible from Other Scripts for proper singleton configuration.
Shared by default. Unique by choice. That is the Godot resource model.