#How to cast get_nodes_in_group()

1 messages · Page 1 of 1 (latest)

latent umbra
#

Hi everyone ! I'm working on reproducing a tutorial for an RTS Game on Godot 4.2, but i'm also improving the code a bit. I'm trying to force static type almost everywhere, but i'm struggling with the following code :

class_name World
extends Node2D

var units: Array[Unit] = []

func _ready() -> void:
    units := get_tree().get_nodes_in_group("units")

func _on_area_selected(object: Camera) -> void:
    var units_selected := get_units_in_area(area)
    for unit in units:
        unit.set_selected(false)
        
    for unit in units_selected:
        unit.set_selected(!unit.selected)

    print("Selected ", units_selected.size(), " unit", "s" if units_selected.size() > 1 else "")

func get_units_in_area(area: Array[Vector2]) -> Array[Unit]:
    var units_selected: Array[Unit] = []
    for unit in units:
        if unit.position.x >= area[0].x and unit.position.x <= area[1].x and unit.position.y >= area[0].y and unit.position.y <= area[1].y:
            units_selected.append(unit)
    return units_selected

The issue is that get_nodes_in_group return an array of Node, but i expect it to return an array of Unit (which is a class, that extends CharacterBody2D, so it has a position, and my class have some methods that i call in the function _on_area_selected for example, like .set_selected()). I then have an error without even launching the game which is the following :

Value of type "Array[Node]" cannot be assigned to a variable of type "Array[Unit]"

If i only cast it like doing

func _ready() -> void:
    units = get_tree().get_nodes_in_group("units") as Array[Unit]

I only have an error when the game is launched, which is the following :

Trying to assign an array of type "Array[Node]" to avariable of type "Array[Unit]"

So how can i solve this and assign the correct type ?

#

Just for reference, here is what i have currently if i say that my units array is of type Array[Node], which as i said is understandable since the type Node doesn't have those props (but my class have the set_selected method, and CharacterBody2D have a position)

polar palm
#

you'll have to do the cast to the actual values, something like this should work:

var new_array := old_array.map(func(e: Node)->Unit: return e as Unit) as Array[Unit]
#

@latent umbra^

latent umbra
#

I'll see if it works, so if i understand currently, we can't really "deep cast" an array by using Array[Unit], i must iterate through all the element, cast each element to Unit, and then saying it's an Array[Unit] right ?

polar palm
#

alternatively this would be nicer but not sure if it works:

var new_array : Array[Unit] = []
new_array.assign(old_array)
#

assign:

Performs type conversions if the array is typed.
sounds promising but also vague.

#

alternatively alternatively there's also the "manually typed constructor" Array ( Array base, int type, StringName class_name, Variant script ) but that one is a pain to work with and might also not do the cast for you, since it's so lovely undocumented.

latent umbra
# polar palm you'll have to do the cast to the actual values, something like this should work...

This seems to cause issues, here is what i have for now :

func _ready() -> void:
    var array := get_tree().get_nodes_in_group("units")
    var new_array := array.map(func(e: Node)->Unit: return e as Unit) as Array[Unit]
    units = new_array

The game is crashing stating this error :

Trying to assign an array of type "Array" to a variable of type "Array[Unit]" on line with new_array

I'll try the .assign() method

polar palm
polar palm
latent umbra
#

Okay it works with .assign(), but then why won't it work with "as" keyword ? I mean, both are doing type conversion according to .assign() documentation lol

polar palm
#

yeaaah not sure. but if assign works that's good, have the engine do the work for you 😄