Is there an alternative to YSort?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Sumerechny

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?

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

Eric Ellingson | 2019-05-18 22:49

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.

Implement deep/recursive YSort · Issue #1237 · godotengine/godot-proposals · GitHub

QT44 | 2020-07-22 15:57

:bust_in_silhouette: Reply From: eons

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).

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 p_pos=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 ’ p_child->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 move_child() on a Node that is not a direct child. How to fix that? Also, what is the second argument of move_child() 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)

Sumerechny | 2018-02-14 12:15

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.

eons | 2018-02-17 11:08

:bust_in_silhouette: Reply From: literalcitrus

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.

:bust_in_silhouette: Reply From: kiamli

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