C# Custom Signal Not Working

Godot Version 4.2

C# Custom Signal Not Connecting

Hi, I have an issue that throws no errors but the code does not behave as expected. I am following Chris Bradfield’s Godot 4 book, but I am writing the code in C#.
The game recreates “Asteroids”. The asteroid (Rock) objects are created in Main’s _Read() and the initial 3 are created and explode as expected.

The issue is:
I connect the Exploded signal in code at the end of the SpawnRock method, but no new rocks spawn after the initial asteroids explode successfully.

Asteroid/Rock code:

public partial class Rock : RigidBody2D
{
	[Signal]
	public delegate void ExplodedEventHandler(int size, float radius, Vector2 pos, Vector2 vel);

	public Vector2 screenSize = Vector2.Zero;
	int size;
	float radius;
	float scaleFactor = 0.2F;

    public override void _IntegrateForces(PhysicsDirectBodyState2D physicsState)
	{
		var xform = physicsState.Transform;
		xform.Origin.X = Mathf.Wrap(xform.Origin.X, 0 - radius, screenSize.X + radius);
        xform.Origin.Y = Mathf.Wrap(xform.Origin.Y, 0 - radius, screenSize.Y + radius);
		physicsState.Transform = xform;
    }


    public void Start( Vector2 _position, Vector2 _velocity, int _size)
	{
		Position = _position;
		size = _size;
		Mass = 1.5F * size;
		GetNode<Sprite2D>("Sprite2D").Scale = Vector2.One * scaleFactor * size;
		radius = GetNode<Sprite2D>("Sprite2D").Texture.GetSize().X / 2 * GetNode<Sprite2D>("Sprite2D").Scale.X;
		var shape = new CircleShape2D();
		shape.Radius = radius;
		GetNode<CollisionShape2D>("CollisionShape2D").Shape = shape;
		LinearVelocity = _velocity;
		AngularVelocity = (float)GD.RandRange(-Math.PI, Math.PI);
		GetNode<Sprite2D>("Explosion").Scale = Vector2.One * 0.75F * size;
	}

	public async void Explode()
	{
        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("disabled" , true); 
		GetNode<Sprite2D>("Sprite2D").Hide();
		GetNode<AnimationPlayer>("Explosion/AnimationPlayer").Play("explosion");
		GetNode<Sprite2D>("Explosion").Show();
		EmitSignal(SignalName.Exploded, "size", "radius", "position", "linear_velocity");
		LinearVelocity = Vector2.Zero;
		AngularVelocity = 0;
		await ToSignal(GetNode<AnimationPlayer>("Explosion/AnimationPlayer"), AnimationPlayer.SignalName.AnimationFinished);
		QueueFree();
    }
}

Main code:

public partial class Main : Node
{
	[Export]
	public PackedScene rockScene;

	Vector2 screenSize = Vector2.Zero;
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		screenSize = GetViewport().GetVisibleRect().Size;
		for (int i= 0; i<3; i++)
		{
			SpawnRock(3);
		}
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _Process(double delta)
	{
	}
	public void SpawnRock(int size, Vector2? pos = null, Vector2? vel = null)
	{
		if (pos == null)
		{
			GetNode<PathFollow2D>("RockPath/RockSpawn").Progress = GD.Randi();
            pos = (Vector2)GetNode<PathFollow2D>("RockPath/RockSpawn").Position;
        }
		if (vel == null)
		{
			vel = Vector2.Right.Rotated((float)GD.RandRange(0.0, Math.Tau)) * GD.RandRange(50, 125);
		}
		var r = (Rock)rockScene.Instantiate();
		r.screenSize = screenSize;
		r.Start((Vector2)pos, (Vector2)vel, size);
		CallDeferred("add_child", r);
		r.Exploded += OnRockExploded;
              // Uses method defined below to check if the signal is connected
          if (CheckSignal(r))
             {
                 GD.Print("Signal Connected");
             }
             else if (!CheckSignal(r))
             {
                 GD.Print("Signal NOT Connected");
             }
	}

	private void OnRockExploded(int size, float radius, Vector2 pos, Vector2 vel)
	{
		if (size <= 1)
		{
			return;
		}
		int[] offsetArray = new int[] { -1, 1 };
		foreach (int offset in offsetArray)
		{
			var dir = GetNode<RigidBody2D>("Player").Position.DirectionTo(pos).Orthogonal() * offset;
			var newpos = pos + dir * radius;
			var newvel = dir * vel.Length() * 1.1F;
			SpawnRock(size - 1, newpos, newvel);

        }
	}

}

Can any kind soul help me solve this puzzle please?

Edit: I added a method in Main to check if the signal is connected and it seems like it is not even connecting. Any ideas why and how to fix this?

public bool CheckSignal(Rock emitter)
{
    Action<int, float, Vector2, Vector2> CheckOnRockExploded = OnRockExploded;
	return (emitter.IsConnected(Rock.SignalName.Exploded, Callable.From(CheckOnRockExploded)));
}

You are not emitting the signal correctly, it should be EmitSignal(SignalName.Exploded, size, radius, Position, LinearVelocity);

2 Likes

Yep, that solved the issue.
So obvious and I missed it.
Thanks!

PS: My CheckSignal method must be wrong somehow, too. But that’s another question.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.