+1 vote

Hello.

Is there a way to make YSort work with children of its child node? Or is there some alternative of sorting objects in a top down game? I made some nodes children of another node, to make my editor organized, but YSort doesn't sort this node's children and also putting another YSort inside this node solves nothing. Is this normal to have your scenes clustered with all different kinds of nodes or should I change my design approach?

in Engine by (33 points)

I had this problem, specifically with Path2D and PathFollow2D inside of a YSort. This was my solution, which might be useful to you: https://github.com/e-e/better-ysort

Added a proposition to implement this in the core.
Most solutions require people to rewrite ysort themselves and that doesnt help anyone.
Please show support for a deep ysort here.

https://github.com/godotengine/godot-proposals/issues/1237

3 Answers

+2 votes
Best answer

Nodes can be manually sorted by move_child and z_order if Node2D.

So you can create your own YSort using these methods and using groups to locate nodes from all over the scene.

I can't say if that will solve your problem or if what you need is a better scene structure (sometimes is not possible).

by (7,910 points)
selected by

Could you explain to me how does move_child() work? I get these errors:

0:00:27:0826 - Index p_pos=10 out of size (data.children.size() + 1=3)

Typ:Błąd
Opis:
Czas: 0:00:27:0826
C Błąd: Index ppos=10 out of size (data.children.size() + 1=3)
C Źródło: scene\main\node.cpp:308
C Funkcja: Node::move
child

0:00:31:0376 - child is not a child of this node.

Typ:Błąd
Opis: child is not a child of this node.
Czas: 0:00:31:0376
C Błąd: Condition ' pchild->data.parent != this ' is true.
C Źródło: scene\main\node.cpp:310
C Funkcja: Node::move
child

My Nodes are organied like this:
Game
-Chests
--Chest1
--Chest2
--Chest3
-Player

And I'm trying to move a specific Chest, not the whole Chests node, through a method called in Game script. I think these errors are because I'm calling movechild() on a Node that is not a direct child. How to fix that? Also, what is the second argument of movechild() referring to? The Z index, or the amount of children within a Node?

extends Node

func _on_PlayerRange_body_entered(body):
    var bodypath = body.get_path()
    var bodyname = body.name
    var bodynode = get_node(bodypath)
    print(bodynode.name)
    print(bodypath)
    if bodyname != "Player":
        var playerposition = get_node("Player").position
        var bodyposition = bodynode.position
        print(bodyposition.y)
        print(playerposition.y)
        if bodyposition.y > playerposition.y:
            move_child(bodynode, 10)
        else:
            move_child(bodynode, 1)

move_child changes the index order of the children (affecting draw order in the process), the error says the node you are trying to move is not a child of that node, and index is bigger than child count too.

+2 votes

YSort only affects the draw order of its immediate children. Writing your own custom YSort node that does a deep search for any Node2D inherited nodes and changes their Z index based on their Y position is a possible solution. You will most likely need to also disable the Z As Relative property to handle the multiple depths. For reference, a node with a higher Z index is drawn on top of one with a lower index. Think of the positive Z direction coming out of the screen towards you.

A quick and easy Y-sort hack is to just set the Z index to be the negative of the y position of a node, and disable relative z index. Further up the screen means a lower y position, so negating it gives you a value higher than nodes below it. Not recommended as a final solution because of a myriad of problems (large position values, subpixel values, etc) but it can work initially.

From a design approach, in theory every node should serve a functional purpose, but realistically using a Node to bundle up similar objects doesn't break anything (and pretty much everyone does it). Problems can arise though, such as the one you're having now, but most common nodes are designed to be fairly self-contained. To be honest, YSort has always been a notoriously difficult node to work with because of its limitations and writing your own solution that lets you be more selective about what nodes are being Y-sorted is never a bad idea if you'll get some good use out of it.

by (524 points)
+1 vote

Not sure if this still relevant, but you can nest YSort nodes and each of their children will be sorted at the same time.

by (16 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.