Godot: Sprite/ColorRect: using "onready var" reference won't visually update the rect_size/scale during runtime

Created on 20 Oct 2020  路  3Comments  路  Source: godotengine/godot

Godot version: 3.2.3 stable

OS/device including version: Win64

Issue description:
I have a node 2D with a ColorRect as child and want to change the rect_size in code:

this works
extends Node2D

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        $ColorRect.rect_size.x += 10
        print($ColorRect.rect_size.x)
this does not work
extends Node2D

onready var color_rect_x = $ColorRect.rect_size.x

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        color_rect_x += 10
        print(color_rect_x)

Both will print the rect_size changes correctly in the output panel, but in the onready var example, the visual representation of the ColorRect does not change. As expected, assigning the ColorRect to the variable in _ready() has the same effect as onready var.

Same applies to Sprite:

works
extends Node2D

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        $Sprite.scale.x += 0.1
        print($Sprite.scale.x)
does not work
extends Node2D

onready var sprite_scale_x = $Sprite.scale.x

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        sprite_scale_x += 0.1
        print(sprite_scale_x)
archived core

Most helpful comment

Unless I misunderstand something, your code examples are not equivalent at all.
In your work examples, you increment the scale property of the node directly, so yeah it updates the node.
In your does not work examples, you put the scale in a member var, and increment the member var. This will obviously not update the node. Number variables are not references, so that's expected.

In other words:

$Sprite.scale.x += 0.1

Is actually syntactic sugar for doing this:

$Sprite.scale = Vector3($Sprite.scale.x + 0.1, $Sprite.scale.y)

(which btw is a GDScript thing, won't work in C# I believe)

If you want your onready var to apply to the node, in any case, you have to assign the property of the node:

sprite_scale_x += 0.1
$Sprite.scale.x = sprite_scale

Note, you can also do this:

extends Node2D

onready var sprite = $Sprite

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        # Works because Sprite inherits Object, which is stored by reference, unlike plain numbers
        sprite.scale.x += 0.1
        print(sprite_scale_x)

All 3 comments

Unless I misunderstand something, your code examples are not equivalent at all.
In your work examples, you increment the scale property of the node directly, so yeah it updates the node.
In your does not work examples, you put the scale in a member var, and increment the member var. This will obviously not update the node. Number variables are not references, so that's expected.

In other words:

$Sprite.scale.x += 0.1

Is actually syntactic sugar for doing this:

$Sprite.scale = Vector3($Sprite.scale.x + 0.1, $Sprite.scale.y)

(which btw is a GDScript thing, won't work in C# I believe)

If you want your onready var to apply to the node, in any case, you have to assign the property of the node:

sprite_scale_x += 0.1
$Sprite.scale.x = sprite_scale

Note, you can also do this:

extends Node2D

onready var sprite = $Sprite

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        # Works because Sprite inherits Object, which is stored by reference, unlike plain numbers
        sprite.scale.x += 0.1
        print(sprite_scale_x)

Closing per @Zylann's comment.

Thank you for the thorough explanation, @Zylann , that totally makes sense!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zatherz picture zatherz  路  121Comments

NullNeska picture NullNeska  路  191Comments

willnationsdev picture willnationsdev  路  93Comments

reduz picture reduz  路  111Comments

RiverMesa picture RiverMesa  路  142Comments