Accessing members from instantiated scene in C#

Godot Version

4.2.2 Mono

Question

Hi. I am trying to access variables and functions from an instantiated scene in C#, but it doesn’t seem to work.

In GDScript it works perfectly fine.

Main scene script (GDScript):

extends Node2D

var player: PackedScene = preload("res://Scenes/Player/Player.tscn")

func _ready() -> void:
	var new_player: CharacterBody2D = player.instantiate() as CharacterBody2D
	new_player.position = Vector2(150, 150)
	new_player.health = 200
	new_player.say_hello()
	add_child(new_player)

Player scene script (GDScript):

extends CharacterBody2D

var health: int = 100

func _ready() -> void:
	print(str("player health: ", health))

func say_hello() -> void:
	print("Hello!")

Output:

Hello!
player health: 200

Main scene (C#):

using Godot;

namespace CsharpTestProject.Scenes.Main;

public partial class Main : Node2D
{
    private PackedScene _player = GD.Load<PackedScene>("res://Scenes/Player/Player.tscn");
    
    public override void _Ready()
    {
        CharacterBody2D newPlayer = _player.Instantiate<CharacterBody2D>();
        newPlayer.Position = new Vector2(500f, 200f);
        newPlayer.Health = 200;
        newPlayer.SayHello();
        AddChild(newPlayer);
    }
}

Player scene (C#):

using Godot;

namespace CsharpTestProject.Scenes.Player;

public partial class Player : CharacterBody2D
{
    public int Health = 100;

    public override void _Ready()
    {
        GD.Print("player health: " + Health);
    }

    public void SayHello()
    {
        GD.Print("Hello!");
    }
}

Instantiating newPlayer at a specific position works fine, however, accessing any explicitly defined member in its script (unlike CharacterBody2D.Position) produces the following errors:

“Cannot resolve symbol ‘Health’”
“Cannot resolve symbol ‘SayHello’”

Is this just a syntactical error, or am I missing some core principle of either C# programming or Godot C# integration?

Thanks in advance!

Health and SayHello are Player members.
Your newPayer variable is of type CharacterBody2D. Try changing it’s type to Player.

1 Like

That seemed to work! Thanks a lot : )

It does however require me to put Player.Player instead of just Player.

Is there a way to instantiate classes in my scripts without having to prefix them with (what i assume is) their respective namespaces?

From

Player.Player newPlayer = _player.Instantiate<Player.Player>();

to

Player newPlayer = _player.Instantiate<Player>();

Thank you!

It’s not a common practice to have an exclusive namespace per class. I’d recommend to have Main and Player inside CSharpTestProject.Scenes.

If you want to have them in different namespaces you could put Player in CSharpTestProject.Scenes.Entities, or something like that. Then, in the top of your Main class script you add using CSharpTestProject.Scenes.Entities.

1 Like