2
\$\begingroup\$

I have been trying to split a game object in half, starting with splitting the collision shape in half. I create two new clones of the split object, then give them a property to be assigned to the collision polygon. In the editor, the setup looks like this:

enter image description here

The health_xxx are sprites to be changed based on how damaged it is. In code, I do this:

      // two paths created from the original shape
      std::array<PackedVector2Array*, 2> paths {&path1, &path2};
      
      for (const auto* path : paths)
      {
        ShootableObject* myCopy = (ShootableObject*)duplicate(DUPLICATE_SIGNALS & DUPLICATE_SCRIPTS);
        // this is the path to be assigned when the object is ready
        myCopy->collisionOverride = *path;
        get_parent()->add_child(myCopy);
      }

In _ready, I tried to do find_child and Object::cast_to, but that doesn't work. The following code works and demonstrates my problem:

  if (collisionOverride.size() > 0)
  {
    CollisionPolygon2D* collision = Object::cast_to<CollisionPolygon2D>(find_child("collision"));
    if (collision)
    {
      // never happens
      collision->set_polygon(collisionOverride);
    }
    else
    {
      UtilityFunctions::print("Cannot override collision, node not found! Trying alternative method");
      for (int i = 0; i < get_child_count(); ++i)
      {
        Node* child = get_child(i);
        if (child->get_name() != StringName("collision"))
        {
          continue;
        }
        if (collision = Object::cast_to<CollisionPolygon2D>(child))
        {
          // this works
          collision->set_polygon(collisionOverride);
          UtilityFunctions::print("Success.");
          break;
        }
      }
    }
  }

The output I get:

Cannot override collision, node not found! Trying alternative method
Success.

I just don't understand why do I have to reimplement find_child in this case. Even stranger is the fact that for nodes that exist from the start, this is not a problem.

I am using Godot 4.2.

\$\endgroup\$
1
  • \$\begingroup\$ Try find_child("collision",false,false) insdead. \$\endgroup\$
    – Mangata
    Oct 27, 2023 at 6:48

1 Answer 1

3
\$\begingroup\$

find_child docs say:

Node find_child ( String pattern, bool recursive=true, bool owned=true ) const

...

If owned is true, this method only finds nodes who have an assigned owner. This is especially important for scenes instantiated through a script, because those scenes don't have an owner.

Creating clones sounds like spawning the nodes via script, so they don't have owners.

In your hierarchy, you don't need recursive either. When you don't need recursive, it's good to disable it because find_child searches depth first.

So as Mangata said, use find_child("collision", false, false).

\$\endgroup\$
3
  • \$\begingroup\$ Should I set the owner for the clones, or does it matter at all? \$\endgroup\$ Oct 28, 2023 at 13:40
  • \$\begingroup\$ The Node docs say "[the owner property] keeps track of who instantiated what. This is mostly useful when writing editors and tools, though." So I don't think it matters unless you're writing @tool, code saving PackedScenes, or other editor code. \$\endgroup\$
    – idbrii
    Oct 30, 2023 at 22:28
  • \$\begingroup\$ @TomášZato Explicitly (un)setting a Node's owner is useful for certain operations, e.g. selectively serialising Nodes in a branch in a recursive fashion to save/load them in/from a file. In your case, just using additional arguments when calling the find_child() function should do the work. \$\endgroup\$
    – liggiorgio
    Nov 10, 2023 at 21:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .