Godot Version
v4.4.beta4.official [93d270693]
Question
I sometimes check if all required parameters of a function are set and skip it if any is missing.
One way to do that is:
func someFunction() -> void:
if [requiredProp1, requiredProp2].has(null):
return
# code that gets executed when the above passes
But that doesn’t always work when the checked property is a null object (prints as <Object#null>
), for example, if you set a new Texture2D
and then want to immediately call get_image()
, e.g.
var texture_image := texture.get_image()
the return value may initially still be a null object. I suspect that setting a new Texture2D
may take some time to be ready, and so:
[texture_image, etc].has(null)
doesn’t catch that null object.
There are workarounds, for example:
[texture_image, etc].any(func (item:Variant) -> bool: return item == null)
or individually, e.g.
texture_image == null
work just fine.
Do I misunderstand the use case for Array.has()
or is this something that should behave differently?
I have the workaround, but it’s just something that annoys me because I don’t fully understand it.
Here’s a simplified real-world example that updates a CollisionShape3D
based on a height map:
@tool
extends CollisionShape3D
@export var terrain_map:Texture2D:
set(value):
terrain_map = value
update()
@export var terrain_amplitude:float = 25.0:
set(value):
terrain_amplitude = value
update()
@export var surface_map:Texture2D:
set(value):
surface_map = value
update()
@export var surface_amplitude:float = 2.0:
set(value):
surface_amplitude = value
update()
func update() -> void:
if [terrain_map, surface_map].has(null):
# skip this function until all required properties are set; this works fine
prints("Updating ground_collision_shape failed. Not all required properties are set.")
return
var terrain_map_image := terrain_map.get_image()
var surface_map_image := surface_map.get_image()
if [terrain_map_image, surface_map_image].has(null):
# this does not work reliably because terrain_map_image may be a null object <Object#null>, even if terrain_map is clearly set
prints("Updating ground_collision_shape failed. Cannot get image from terrain_map or surface_map.")
return
# if the above check for terrain_map_image fails to detect the null object, the following line will create a fatal error,
# "Cannot call method 'get_width' on a null value."
shape.map_width = terrain_map_image.get_width()
shape.map_depth = terrain_map_image.get_height()
# updating the CollisionShape3D shape based on the terrain map and a terrain amplitude
terrain_map_image.convert( Image.FORMAT_RF )
surface_map_image.convert( Image.FORMAT_RF )
shape.update_map_data_from_image(terrain_map_image, 0, terrain_amplitude)