What is the best workflow for editing parts of nested resources meant to be used by multiple nodes within a scene?

Godot Version

4.4

Question

Hi,

I’m starting out on a project to make a top-down tactical 2d grid-based game in the vein of Fire Emblem.

In order to store information about different units, I’ve made a custom Resource “Unit”:

class_name Unit
extends Resource

@export var sprite_frames: SpriteFrames
# Other stuff...

My plan is to use this to contain everything relevant to a given type of unit, and then have a generic “UnitInstance” scene which I can instantiate, inject a Unit Resource as a dependency, and then have it configure itself dynamically based on that.

For example, the Unit needs to display a sprite, so my plan was to nest a SpriteFrames resource within each Unit, and then have the UnitInstance assign the SpriteFrames to an AnimatedSprite2D child node when its unit property is set.

class_name UnitInstance
extends Node2D

@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D

@export var unit: Unit:
    set(value):
        unit = value
        sprite.sprite_frames = unit.sprite_frames
# Other stuff...

My question is, is there a way that I can see this happen in the editor, so I can work on the properties of each unit and see them change visibly? I have tried just adding @tool to the top of the UnitInstance script, but it doesn’t seem to work, so I wondered if I was missing something, or if this just isn’t a sensible way to structure my project… I suppose an alternative would be scene inheritance, but all of the advice I have seen is to avoid that if at all possible.

Any help anyone could provide would be much appreciate.

Thanks!

You need to add @tool to all the scripts that need to be executed in the editor. In this case both Unit and UnitInstance should have @tool set.

If you have properties that want to be reflected in the scene like a name:String that you want to show inside a Label node in the scene then such modifications to the resource won’t be automatically propagated. You’ll need to create setters that call Resource.emit_changed() and connect to the Resource.changed signal to update the Label.

Setting the sprite_frames this way won’t work as sprite won’t be available when the setter gets called while the script is being initialized.

You should do something like:

@export var unit: Unit:
    set(value):
        unit = value
        if not is_node_ready():
            await ready
        sprite.sprite_frames = unit.sprite_frames

To wait until the node is ready to access its children.