-
Notifications
You must be signed in to change notification settings - Fork 258
Move generic sequence puzzle object scene to NO_EDIT template #1844
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
base: main
Are you sure you want to change the base?
Move generic sequence puzzle object scene to NO_EDIT template #1844
Conversation
Previously this tool could handle two ways that scene A can reference some scene B that is also in the NO_EDIT template: 1. As a PackedScene property assigned to a node in scene A 2. Referred to by UID or path in a string property of a node in scene A However, it could not handle the case where scene B is instantiated into scene A. Supporting this allows us to explore a model where, rather than StoryQuests instantiating a shared scene (such as player.tscn, throwing_enemy.tscn, or sequence_puzzle_object.tscn) and overriding properties on each instance of it, they instead contain their own copy of such scenes, and can customize that copy, once. This makes it much easier to make changes like adjusting the collision shapes without accidentally modifying shared scenes used elsewhere in the game. #1150 Doing this requires several steps: 1. Duplicate the instanced scene B as a new scene C, using existing logic; 2. Instance the new scene; 3. Replace the original instance with the new instance, preserving the name (which is part of the API of the scene), children, and any properties that were overridden. Node.replace_by() almost does step 3, except that it does not preserve the name, and it has the very weird behaviour of changing the replacement node to be an instance of whatever the original node was an instance of: exactly the opposite of what we are trying to achieve.
Previously we had one scene with the sequence_puzzle_object.gd script attached at its root, with a generic white circle as the sprite. This scene was then instantiated in every scene that uses this puzzle, and on every instance in each scene, the SpriteFrames were overridden appropriately. The problem with doing this is that it only really works if the sprite matches the collision & interaction shapes of the generic asset. (In fact these shapes did not match the generic asset: they were created based on the musical rocks!) We either ignored this issue, or used the Editable Children feature to tweak the collision shapes as needed. In recent commits this has changed: - musical_rock.tscn represents the specific rock that is used in the musician quest; it is configured with the rock SpriteFrames and matching shapes. - champ_sequence_puzzle_object.tscn uses a subclass of the sequence_puzzle_object.gd script, and has its own collision shapes matching the sprite in that quest. - In Stella, the tortoise is a scene containing six instances of stella_tortoise_shell_gem.tscn. Each gem has sequence_puzzle_object.gd attached but unlike the other instances it is a Node2D rather than a SolidBody2D. The tortoise itself is a single SolidBody2D. The pattern is that it is more flexible to duplicate the scene so that it can be customized for the specific puzzle at hand, while reusing the script. To guide learners in this direction, move the generic object scene into the NO_EDIT template. Our StoryQuest duplicator will duplicate the scene (but not the script!) when duplicating the NO_EDIT template. This will make it easier for the team creating a StoryQuest to adjust the object scene as needed to match their assets without affecting the broader game. (In practice not every team has replaced the generic object sprite, so in this case we will have a duplicate scene for no upside. But scenes are small!) See #1150 for discussion of this general approach.
|
Sorry, meant to open this as a draft. The changes to the duplication logic work in Godot 4.6-rc2 but crash in the current stable release Godot 4.5.1 from Flathub. I have spent several days trying to debug this but I have given up. |
|
|
||
| copied.resource_path = copy_path | ||
|
|
||
| var result := copied.pack(scene) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With Godot 4.5.1 from Flathub the engine segfaults at this line in the case where scene referenced another scene. I can't reproduce it with a local build of the development branch with debug symbols enabled, but I don't know whether this is because some change between 4.5.1 and 4.6-rc2 has fixed whatever the underlying engine bug is, or because I am building with a different toolchain in a way that masks the bug.
I have tried to boil this down to a smaller, reproducible test case, and found some problems along the way, but ultimately I have spent too long on this and have to set it aside. I'm pretty sure my logic above is correct and the engine is buggy (at some level that is obvious because GDScript should not be able to cause a segfault in the engine).
|
Play this branch at https://play.threadbare.game/branches/endlessm/wjt/move-generic-sequence-puzzle-object-scene-to-no-edit-template. (This launches the game from the start, not directly at the change(s) in this pull request.) |
Previously we had one scene with the sequence_puzzle_object.gd script attached
at its root, with a generic white circle as the sprite. This scene was then
instantiated in every scene that uses this puzzle, and on every instance in each
scene, the SpriteFrames were overridden appropriately.
The problem with doing this is that it only really works if the sprite matches
the collision & interaction shapes of the generic asset. (In fact these shapes
did not match the generic asset: they were created based on the musical rocks!)
We either ignored this issue, or used the Editable Children feature to tweak the
collision shapes as needed.
In recent commits this has changed:
musical_rock.tscn represents the specific rock that is used in the musician
quest; it is configured with the rock SpriteFrames and matching shapes.
champ_sequence_puzzle_object.tscn uses a subclass of the
sequence_puzzle_object.gd script, and has its own collision shapes matching the
sprite in that quest.
In Stella, the tortoise is a scene containing six instances of
stella_tortoise_shell_gem.tscn. Each gem has sequence_puzzle_object.gd attached
but unlike the other instances it is a Node2D rather than a SolidBody2D. The
tortoise itself is a single SolidBody2D.
The pattern is that it is more flexible to duplicate the scene so that it can be
customized for the specific puzzle at hand, while reusing the script.
To guide learners in this direction, move the generic object scene into the
NO_EDIT template. Our StoryQuest duplicator will duplicate the scene (but not
the script!) when duplicating the NO_EDIT template. This will make it easier for
the team creating a StoryQuest to adjust the object scene as needed to match
their assets without affecting the broader game.
(In practice not every team has replaced the generic object sprite, so in this
case we will have a duplicate scene for no upside. But scenes are small!)
See #1150 for discussion of
this general approach.