C# - Access error when reinstantiating a scene

Godot Version 4.2.1

Question

I have a prefab for an ability slot, when I pump an ability, the skill prefab is added to the stage in the skillbar. When I reduce the ability’s levlevel to 0, then the skillet is removed from the skillbar. This was working, until the recreate. That is, after I created and deleted the skillet, when I try to create it, it appears, but it is not possible to display the level of the skillet via Label due to an access error.

GUI.cs:

private void _ChangeSkillParameters(int skillID, bool LevelUp)
{
	if ((int)gameManager.SkillParameters[skillID]["Level"] == 0 && !LevelUp)
	{
		DeleteSkillSlot(skillID);
		return;
	}

	if ((int)gameManager.SkillParameters[skillID]["Level"] == 1 && LevelUp)
	{
		AddSkillSlot(skillID);
		return;
	}
}

public void AddSkillSlot(int skillID)
{
	SkillSlot skill = skillReference.Instantiate() as SkillSlot;
	skillBar.AddChild(skill);

	skill.SetSkill(skillID);
	skill.StartAnimation();
}

public void DeleteSkillSlot(int skillID)
{
	for (int i = 0; i < skillBar.GetChildren().Count; i++)
	{
		SkillSlot skill = skillBar.GetChild(i) as SkillSlot;
		if (skill.GetSkill() == skillID)
		{
			skill.DeleteSkillSlot();
			break;
		}
	}
}

SkillSlot.cs:

public override void _Ready()
{
	gameManager = GetNodeOrNull("/root/GameManager") as GameManager;
	gameManager.ChangeSkillParameters += _ChangeSkillParameters;

	skillBox = GetNode("SkillBox") as TextureRect;
	skillTexture = skillBox.GetNode("SkillTexture") as TextureRect;
	levelLabel = GetNode("LevelLabel") as Label;
	animationPlayer = GetNode("AnimationPlayer") as AnimationPlayer;
}

private void _ChangeSkillParameters(int skillID, bool LevelUp)
{
	if (this.skillID == skillID)
	{
		levelLabel.Text = Convert.ToString((int)gameManager.SkillParameters[this.skillID]["Level"]);
	}
}

public void SetSkill(int skillID)
{
	this.skillID = skillID;
	SetTexture(this.skillID);
}

public int GetSkill()
{
	return this.skillID;
}

public void SetTexture(int skillID)
{
	skillTexture.Texture = (Texture2D)gameManager.SkillParameters[skillID]["Texture"];
}

public void StartAnimation()
{
	animationPlayer.Play("start");
}

public async void DeleteSkillSlot()
{
	animationPlayer.PlayBackwards("start");
	await ToSignal(animationPlayer, AnimationPlayer.SignalName.AnimationFinished);
	QueueFree();
}


P.S. Here’s the bug report, also found a quote about it on stackoverflow.

" Srv_LoginChannelFactory.Close() is where it’s being disposed. When you call close you are giving up whatever unmanaged resource you had. Attempting to do something other then inspecting its state or re-opening it results in the “Cannot access a disposed object” exception. This is true whenever you close a disposable object and try and do something with it afterwards. For example writing to a file that’s closed, or executing a sql statement on a closed database connection. "

I can’t find the cause of the problem, if you can help, I will be very happy

The essence of the fable is this - REMOVE SIGNAL RELATIONSHIPS WHEN REMOVING NODES.

Well, my big brain, after working my ass off, has come to the right conclusion. The error occurred in the signal of changing parameters ChangeSkillParameters of the Skillslot. Thinking about it, I assumed that we bind the signal by creating a new connection at the gameManager, which is preserved even after deleting a node via QueueFree(). This implies that after the “death” of a slot node, there was a phantom signal connection to the dead node, where the signal was received but could not be accessed due to the absence of a “live” node. Therefore, at the “death” of the node, I began to unlink the signal from the gameManager and everything worked. I didn’t think that a smart idea could come to my sleepy head.

public async void DeleteSkillSlot()
{
	gameManager.ChangeSkillParameters -= _ChangeSkillParameters; // NEW STRING
	animationPlayer.PlayBackwards("start");
	await ToSignal(animationPlayer, AnimationPlayer.SignalName.AnimationFinished);
	QueueFree();
}

Thank you, good man.

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