Godot Version
4.5.1, .NET version
Question
Hello everyone
I am working on a strategy game, and I need to make a menu appears when the player moves a unit, in order to know what is the action
For that, here’s the plan :
Once the unit moved, it sends a signal (or an event, as I use C#) to the top node, that triggers this method
/// <summary>
/// Event handler that looks at what the unit can and cannot do
/// </summary>
/// <param name="sender">C# convention, must give the object</param>
/// <param name="unit">Unit given by the signal</param>
private void UnitActions(object sender, Unit unit)
{
// Code checking what can the unit do
//...
//...
// Creation of the menu
actionMenu = new ActionMenu(unit);
AddChild(actionMenu);
}
Here’s what the ActionMenu class looks like :
public partial class ActionMenu : VBoxContainer
{
Unit unit;
List<ControlActBase> controls = [];
readonly FactoriesControlRegistery FactoriesControl = new();
public ActionMenu(Unit u)
{
unit = u;
Update();
}
public void Update()
{
controls.Clear();
List<IUnitAction> unitActions = unit.GetAllActions();
foreach (IUnitAction item in unitActions)
{
ControlActBase tmpControl = FactoriesControl.Create(item,unit); // create an appropriate ControlAct
controls.Add(tmpControl);
AddChild(tmpControl);
}
}
}
If I should give you a visual example to what is what, here’s a screenshot from Wargroove, one of my inspirations, to show you how I do it
Here, there are 3 “ControlActBase”, with the ActionMenu as their containerNow, the main problem. Here’s the scene for a ControlActBase, or rather, its children :
As you can see, both have a script attached to itHere are every class. NB : They are in different files, I only gathered them in one code window for convenience
/*ControlActBase.cs*/
/// <summary>
/// Althought this class isn't noted abstract, do not use it directly
/// This class exists as it is, as a base for the concrete class ControlAct, as a way to implicitely convert
/// ControlAct into one common class
/// It's simply not abstract because it inherits from a non abstract class
/// </summary>
public partial class ControlActBase: AspectRatioContainer{}
/*ControlAct.cs*/
/// <summary>
/// The ControlAct class is one of the action that can be selected after the unit moved.
///When selected, the IUnitAction attached to it
/// </summary>
/// <typeparam name="T">The IUnitAction attached to the ControlAct. It must NOT be abstract</typeparam>
public partial class ControlAct<T> : ControlActBase where T : IUnitAction,new()
{
// Onready
ButtonAction buttonAction;
readonly IUnitAction unitAction = new T();
public Unit unit;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
GD.Print("ControlAct ready");
buttonAction = GetNode<ButtonAction>("ButtonAct");
buttonAction.Pressed += DoAction; // subscribe the event
buttonAction.Text = unitAction.DisplayName;
}
public override void _ExitTree()
{
buttonAction.Pressed -= DoAction; // Always unsubscribe events when exittree
base._ExitTree();
}
private void DoAction()
{
if(unit is not null)
{
unitAction.Execute(unit);
}
}
/// <summary>
/// Creates a control, ready to be used by the menu of actions
/// </summary>
/// <typeparam name="T">The type of action to create</typeparam>
/// <param name="unit">The unit that will do it</param>
/// <returns>The control that will be used for the menu</returns>
public static ControlAct<T1> CreateControl<T1>(Unit unit) where T1:IUnitAction,new()
{
ControlAct<T1> control = new();
control.SetUnit(unit);
return control;
}
}
/*ButtonAction.cs*/
///<summary>
/// A button, but that I could eventually reshape however I want
/// </summary>
public partial class ButtonAction : Button
{
// Called when the node enters the scene tree for the first time.
public override void _EnterTree()
{
base._EnterTree();
GD.Print("Create ButtonAction");
}
}
I must precise, they are all in the same namespace, so they all know eachother
Now, let’s go to the moment in game where this happens

More details on the first one, the debugger tells me that the line in my code that triggers the problem is this one :
/*ControlAct.cs*/
public override void _Ready()
{
GD.Print("ControlAct ready");
buttonAction = GetNode<ButtonAction>("ButtonAct"); // <--- this one precisely
buttonAction.Pressed += DoAction; // subscribe the event
buttonAction.Text = unitAction.DisplayName;
}
If you need more informations on my code, I’ll try to answer ASAP to any of your questions
Thank you in advance

