Godot Version
Godot_4.2.2-stable
Question
I can’t figure out why the color isn’t changing through my script. the script is attached to the root node and the MeshInstance2D is a child.
I’ve also tried self_modulate and tried placing the command in func _process(delta):.
@onready var baseColor = $MeshInstance2D.modulate
func _init():
baseColor = Color(255, 0, 0, 255)
- $MeshInstance2D is a reference to a node ($ is essentially get_node()), while
- $MeshInstance2D.modulate is a property of a node
Essentially your onready statement as it is, is assigning the current value of $MeshInstance2D.modulate to ‘baseColor’. Then when you change baseColor in _init(), all your doing is updating this arbitrary variable called baseColor, not the MeshInstance2D’s modulate property.
try:
# get the initial color if needed for later, or remove entirely
@onready var baseColor = $MeshInstance2D.modulate
func _init():
$MeshInstance2D.modulate = Color(255, 0, 0, 255)
This is the error that I get when I do it like that.
Have you moved or renamed ‘MeshInstance2D’ ?
This implies this node does not exist as a child of the node running this script.
I don’t think I’ve changed anything.
Oh, move it into _ready()
(should wait for all children to be setup while I think init is firing before)
As this is now chosen as the solution I have updated to make it abundantly clear what is happening in the OP.
Essentially there were two issues:
-
You can’t directly reference basic types in GDscript, only Objects (not their properties), so
@onready var baseColor = $MeshInstance2D makes baseColor a reference to the node,
@onready var baseColor = $MeshInstance2D.modulate is direct assignment, making baseColor the value of modulate.
-
Accessing child properties can’t be done in _init()
This is shown in the testable code below:
extends Node2D
@onready var baseColor = $MeshInstance2D.modulate
func _init():
print("Init : baseColor:" + str(baseColor)) # this will print <null> as at this point the @onready has not fired.
baseColor = Color(255, 0, 0, 255) # we then overwrite baseColor (which is not an object's property), noting this is in the HDR range now
print("Init : baseColor:" + str(baseColor)) # then this will now print the updated baseColor
# All of the below will fail, as the MeshInstance2D child is not setup yet. #Uncomment to test
#print("Init : MeshInstance Modulate:" + str($MeshInstance2D.modulate))
#$MeshInstance2D.modulate = baseColor
#print("Init : MeshInstance Modulate 2:" + str($MeshInstance2D.modulate))
func _ready() -> void:
print("Ready : baseColor:" + str(baseColor)) # this will print MeshInstance2D's original modulate property as the @onready assignment has copied this value to the vbariable BaseColor
baseColor = Color(255, 0, 0, 255) # we then overwrite baseColor (which is not an object's property), noting this is in the HDR range now
print("Ready : baseColor:" + str(baseColor)) # then this will now print the updated baseColor variable
print("Ready: MeshInstance Modulate (from changing baseColor):" + str($MeshInstance2D.modulate)) # this will still print the original MeshInstance2D modulate proprty as it is unchanged
$MeshInstance2D.modulate = baseColor # this changes it
print("Ready: MeshInstance Modulate (from assigning to property):" + str($MeshInstance2D.modulate)) # this will now print the updated MeshInstance2D modulate property
Which, assuming you started with a Blue modulate like I did, should output this:
And if you uncomment the block in _init() I commented out:
Re. later comments, the Color constructor is not clamped to 0-1 (HDR allows for higher values) so is not the cause of the error. As such this would still produce a Red MeshInstance2D, though turning on HDR/Glow will likely result in unexpected results.
1 Like
Color has no constructor that takes RGBA values other than 0 to 1 (float)
Try using Color(1, 0,0,1)
Documentation on the constructors.
like @sancho2 said, or you can just Color8(255,0,0,255)
Color8