Godot Version
4.3
Question
`So I am messing around trying to make a simple 2d platformer. The player can point around a gun that shoots and kills enemies. I have set up a health system using component nodes that get parented to each enemy. The only missing link here is getting the gun to damage the enemies.
I have a Node2D with a gun script. This gun uses a separate Raycast2D node to shoot. This ray collides with an Area2D node that has a custom health script on it. When the gun hits the Area2D, I want to send a signal that decreases health on the attached health script.
This is the whole gun script, mildly simplified.
using Godot;
public partial class gunscript : Node2D
{
[Signal] public delegate void SendDamageEventHandler(float somedamage);
[Export] public RayCast2D myRaycast;
Vector2 targetPos = Vector2.Zero;
public override void _PhysicsProcess(double delta)
{
targetPos = GetLocalMousePosition();
Vector2 aimNormal = (targetPos - this.Position).Normalized();
if (Input.IsActionJustPressed("shoot"))
{
myRaycast.TargetPosition = aimNormal * 1000f;
myRaycast.ForceRaycastUpdate();
Area2D hit;
if (myRaycast.IsColliding())
{
//!!!PROBLEM HERE!!!
}
}
}
}
The unknown problem starts right when I try to have something happen when the raycast detects a hit. The goal is to take the Area2D I collide with, connect to the Area2D’s “HealthComponent” script, and decrease health by 1.
I have tried looking for several solutions, however I started out using my incompetent C# intuition. I would think it would be possible to do something like in the following two examples, but that’s unfortunately not how things work.
if (myRaycast.IsColliding())
{
//CS0308 The non-generic method 'RayCast2D.GetCollider()' cannot be used with type arguments
HealthComponent health = myRaycast.GetCollider<HealthComponent>();
//do not know what to do afterwards if the above line would have worked
}
Area2D hit;
if (myRaycast.IsColliding())
{
hit = (Area2D)myRaycast.GetCollider();
//CS0030 Cannot convert type 'Godot.Area2D' to 'HealthComponent'
HealthComponent health = (HealthComponent)hit;
//do not know what to do afterwards if the above line would have worked
}
I have seen plenty of gdscript tutorials giving examples of code that works. These specific examples are impossible for me to translate either due to functional differences or lack of deep C# knowledge. As far as I’m aware, there is no way to directly translate the following example into C#.
area2d hit
if myRaycast.is_colliding():
hit = myRaycast.get_colliding()
if hit is HealthComponent:
var health : HealthComponent = hit
health.damage(1.0)
A dubious website that claims to be able to translate gdscript to C# gave a result that showed me a kind of solution I didn’t know about. The way it does the second “if” statement seems like it could work, but makes no sense either to me or to the compiler.
Area2D hit;
if (myRaycast.IsColliding())
{
//CS8121 An expression of type 'Area2D' cannot be handled by a pattern of type 'HealthComponent'.
if (hit is HealthComponent health)
{
health.Damage(1.0f);
}
}
The most obvious solution to a normal person would be to use a signal, but I feel like I’m missing critical knowledge for this specific scenario. After about an hour of searching, I came across the Connect function to connect signals to each other. I’m not able to intuit how it should work, and I cant understand what the documentation for C# signals is telling me to do. From my understanding, it is incredibly easy to link signals between built-in nodes, but incredibly hard to link custom signals provided by an attached script.
Area2D hit;
if (myRaycast.IsColliding())
{
//CS0103 The name 'Damage' does not exist in the current context
hit.Connect(gunscript.SignalName.SendDamage, Callable.From(TakeDamage), (uint)GodotObject.ConnectFlags.OneShot);
//do not know what to do afterwards if the above line would have worked
}
I cant simply EmitSignal
once the raycast detects a hit, since the signals required can’t be connected by hand in the editor. The game is generative, I have no idea when or where what kinds of enemies will be placed around. I am very tired and withered from clawing for solutions. Forums are my last resort here. Any input would be heavily appreciated.
`