Skip to content

Faulty downcasting #158

@jiaxiongjiao

Description

@jiaxiongjiao

Following up from discord that Gd::try_cast can cast to any derived class.

Both Player and Enemy inherits from CharacterBody3D and can be seen and selected from Godot engine editor.
Player request to scan environment.

if input.is_action_pressed("scan".into(), false) {
    self.scan();
}

Implementation of scan() method.

pub fn scan(&self) {
    print_to_godot(&["=====".to_variant()]);

    let area3d: Gd<Area3D> = self.get_node_as::<Area3D>("ScanArea");
    let near_nodes: Array<Gd<Node3D>> = area3d.get_overlapping_bodies();

    if near_nodes.len() != 0 {
        let first_node: Gd<Node3D> = near_nodes.get(0);

        print_to_godot(&["The first node is: ".to_variant(), first_node.to_variant()]);
        
        // Downcasting first node to Enemy
        let possible_enemy: Option<Gd<Enemy>> = first_node.try_cast::<Enemy>();  // HERE: Downcast to Enemy

        if let Some(enemy) = possible_enemy {
            print_to_godot(&["This is an Enemy: ".to_variant(), enemy.to_variant()]);
        } else {
            print_to_godot(&["Not Enemy type".to_variant()]);
    }

    print_to_godot(&["=====".to_variant()]);
}

Output:

=====
The first node is: Player:<Player#30635197676>
This is an Enemy: Player:<Player#30635197676>
=====

If I change the downcast section to downcast to Player. (The first node did not change. It's still a Player node):

// Downcasting first node to Player
let first_node: Gd<Node3D> = near_nodes.get(0);
let possible_player: Option<Gd<Player>> = first_node.try_cast::<Player>();  // HERE: Downcast to Player

if let Some(player) = possible_player {
    print_to_godot(&["This is a Player: ".to_variant(), player.to_variant()]);
} else {
    print_to_godot(&["Not Player type".to_variant()]);
}

Outputs:

=====
The first node is: Player:<Player#30719083757>
This is a Player: Player:<Player#30719083757>
=====

Conclusion

Basically, the first node, a Player node, can get downcasted into both Player and Enemy.

More:

  • I tried to replicate this in example game. But it worked as expected. Mob did not get downcasted to Player........
  • I don't know how to test Gd<...> alone.

Edit:

  • Ignore TypedArray. It's just Array. Bug still persists after I changed them to Array.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugc: coreCore componentsstatus: upstreamDepending on upstream fix (typically Godot)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions