Skip to content

KoBeWi/Godot-Prefab

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Godot Prefab

Custom class for Godot that extends PackedScene with ability to pack a node recursively and then auto-free it.

But why?

Imagine you have a scene like this:

You have some container with another container that has a few nodes. You want a few copies of the Slot node. Normally you'd just save it as a separate scene, BUT! this is the only place where you will use it and it's just 3 nodes. Totally not worth it to create just another file, which you will have to put somewhere. Such a hassle. If you think otherwise, you could as well stop reading now.

What can be done about it? There are a couple of solutions. The simplest one is just duplicating the Slot node. Something like:

for i in 10:
    var slot = $Slot.duplicate()
    add_child(slot)

There! You now have 10 slots. No wait, it's 11 slots. Also if you want to remove some of them, you have to make sure you don't touch your original Slot, in case you want to make more of them. Also you can't really modify it, because it will break new copies.

So let's be a bit more smart.

onready var slot = $Slot

func _ready():
    remove_child(slot)

    for i in 10:
        add_child(slot.duplicate())

Now you don't have to worry about your original slot breaking, because it's never actually on the scene. You can create as many copies as you want and modify them freely. There's one catch though. You have to make sure that your slot variable is freed, otherwise it will leak. Another thing is that all your node copies will share their sub-resources (which is not always a problem, but still).

A slightly more elegant and safe solution is using PackedScene. You can pack the node and then instance as much as you want, without worrying about leaks etc. The problem is that PackedScene.pack() requires you to set the owner of all children of the node you want to pack. So your code becomes something like:

var slot: PackedScene

func _ready():
    for child in $Slot.get_children():
        child.owner = $Slot

    slot = PackedScene.new()
    slot.pack($Slot)
    $Slot.free() # The original node is not needed, so yeet it.

    for i in 10:
        add_child(slot.instantiate())

It became lengthy though, it would be nice to put it into some method probably.

Luckily, this is exactly what Prefab does:

var slot: Prefab

func _ready():
    slot = Prefab.create($Slot)

    for i in 10:
        add_child(slot.instantiate())

create() method has an optional parameter that determines how the original node will be freed. Possible values are:

  • FREE_MODE_INSTANT - The node is freed using free(). Default.
  • FREE_MODE_DEFERRED - The node is freed using queue_free().
  • FREE_MODE_NONE - The node is not freed.

Example:

Prefab.create($Node, Prefab.FREE_MODE_DEFERRED)

Note that Prefab basically being a PackedScene means that you can save it to a file. It's not the intended usage though.

btw did you know that this plugin's README is longer than the source code? Might be not worth it creating whole repo for something so trivial, but it was useful for me, so it's probably acceptable, idk.


You can find all my addons on my profile page.

Buy Me a Coffee at ko-fi.com

About

Custom class that can be used to easily store part of a scene at runtime.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published