3.3 Signāli un objektu komunikācija
Stundas uzdevums: Apgūt Godot signal sistēmu objektu komunikācijai.
80 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~20 min) - reģistrē un raidi signālu · 2. uzdevums (~25 min) - pieslēdzies signālam no cita objekta · 3. uzdevums (~20 min) - salīdzini signālu ar tiešu izsaukumu · Iesniegšana (~5 min).
Pirms sāc: atver savu projektu ar dalībnieku klasēm. Signāls ir kā paziņojums: viens objekts pasaka "tas notika", bet citi paši izlemj, vai klausīties.
Teorija: Godot signāli (Signals)
Godot signāli ir veids, kā objekti var sazināties bez tieša savienojuma. Viens objekts emit (raida) signālu, citi connect (pievienojas), lai uz to reaģētu.
using Godot;
using System;
public partial class Participant : Node
{
[Signal] public delegate void FinishedEventHandler(string name);
[Signal] public delegate void PenaltyAppliedEventHandler(int amount);
private int energy = 100;
private string participantName = "Anna";
public void ApplyPenalty(int amount)
{
energy -= amount;
EmitSignal(SignalName.PenaltyApplied, amount);
if (energy <= 0)
EmitSignal(SignalName.Finished, participantName);
}
}
Citur kodā:
hero.Finished += OnHeroFinished;
Kā šo izmantot projektā
Atceries: ar redzamu efektu editorā nepietiek. Paskaidro, kura C# klase glabā stāvokli, kura metode to maina un kā Godot node struktūra izmanto šo kodu.
Pārbaudi: katrai būtiskai turnīra lomai ir C# klase vienā .cs failā, ar konstruktoriem, metodēm, signāliem vai mantošanu.
public class OopCheckpoint
{
public string Lesson = "3.3 Signāli un objektu komunikācija";
public bool UsesCSharp = true;
public bool HasScriptFile = true;
public bool HasSingleResponsibility = true;
public bool UsesGodotInspector = true;
}
Praktiskie uzdevumi
1. uzdevums -
Reģistrē un raidi signālu
Beigās tavs objekts pratīs paziņot, ka tas beidzis darbu.
- Nomaini
Participanttā, lai tā mantotu noNode:public partial class Participant : Node. - Pievieno klasē signālu
[Signal] public delegate void FinishedEventHandler(string name);. - Uzraksti metodē
ApplyPenaltypārbaudi, vai enerģija nokritusi līdz 0. - Izsauc tajā
EmitSignal(SignalName.Finished, Name);. - Būvē projektu un pievieno objektu scēnai.
- Pārbaudi Godot editorā cilnē Node -> Signals, vai signāls
finishedtur ir redzams. - Pieraksti, kas notiek, ja
[Signal]rindu izdzēš.
Gatavs, kad: Godot editora Signals sarakstā parādās tavs signāls finished.
2. uzdevums -
Pieslēdzies signālam no cita objekta
Beigās cits objekts uzzinās par notikumu, tieši to nepārbaudot.
- Izveido C# klasi
TournamentManager, kas manto noNode. - Pievieno tai metodi
private void OnParticipantFinished(string name). - Paņem dalībnieku ar
Participant participant = GetNode<Participant>("Participant");. - Savieno
_Ready()metodē signālu arparticipant.Finished += OnParticipantFinished;. - Izdrukā apstrādātājā, kurš dalībnieks beidzis darbu.
- Būvē un samazini dalībnieka enerģiju līdz nullei.
- Pārbaudi Output panelī, ka paziņojums pienāca.
Gatavs, kad: kad dalībnieka enerģija sasniedz 0, menedžeris izdrukā tā vārdu, lai gan pats to nepārbaudīja.
3. uzdevums -
Salīdzini signālu ar tiešu izsaukumu
Beigās tu zināsi, kāpēc signāli ir ērtāki par tiešu saiti.
- Pievieno otru dalībnieku un pieslēdz arī to tam pašam signālam.
- Samazini abu enerģiju un pārbaudi, ka pienāk divi paziņojumi.
- Iedomājies variantu, kur
Participantpats izsauktu menedžeri, un pieraksti, ko tad vajadzētu glabāt katrā dalībniekā. - Pieraksti, kas notiktu ar šo variantu, ja menedžera scēnā nav.
- Atvieno vienu dalībnieku ar
participant.Finished -= OnParticipantFinished;un pārbaudi vēlreiz. - Pieraksti, cik paziņojumu tagad pienāca.
- Pieraksti secinājumu: kurš objekts zina par kuru.
Gatavs, kad: abi dalībnieki raida signālu neatkarīgi, un atvienotais vairs neizraisa paziņojumu.
Papildu uzdevums - Pievieno signālam vairāk datu
Ja pamatdarbs ir gatavs, nodod signālā arī skaitli.
- Papildini signāla delegate ar otru parametru, piemēram atlikušo enerģiju.
- Nodod to
EmitSignalizsaukumā. - Papildini apstrādātāja metodi ar otru parametru.
- Izdrukā abus datus.
- Pārbaudi, ka kompilators sūdzas, ja parametru skaits nesakrīt.
Gatavs, kad: signāls nodod gan vārdu, gan skaitli, un tie abi parādās izdrukā.
Ko sagatavo
Stundas mērķis: Tu proti C# klasē reģistrēt Godot signālu, to raidīt notikuma brīdī un pieslēgt tam citu objektu, un vari izskaidrot, kāpēc signāls ir ērtāks par tiešu izsaukumu.
GitHub krātuvē jābūt:
- Faili ar
[Signal],EmitSignalun+=signāla pieslēgumu. - Ekrānuzņēmums ar Godot Node -> Signals cilni, kurā redzams tavs signāls.
- Ekrānuzņēmums ar Output paneli, kurā redzami abu dalībnieku paziņojumi.
- README.md: viens teikums par to, kurš objekts par kuru zina, lietojot signālus.
Kā iesniedz: Veic commit un push. Skolotāja norādītajā vietā ievieto tikai GitHub krātuves saiti; visiem prasītajiem failiem, README.md pierakstiem un pierādījumiem jābūt pašā krātuvē.
Biežākās kļūdas
- EmitSignal nav efekta: signāls nav pieteikts ar
[Signal]vai netiek izsaukts pareizaisSignalName. - Handler kļūda: apstrādātāja parametru skaitam un tipiem jāsakrīt ar signāla delegate.
- Signāls saņemts vairākkārt:
+=izsaukts vairākas reizes - pieslēdz signālu vienā vietā, parasti_Ready().
Godot ekrānuzņēmumi
Koda piemērs (paplašināts)
using Godot;
using System;
public partial class Participant : Node
{
[Signal] public delegate void PenaltyAppliedEventHandler(int amount);
[Signal] public delegate void FinishedEventHandler(string name);
private int energy = 100;
private string participantName = "Anna";
public void ApplyPenalty(int amount)
{
energy = Math.Max(0, energy - amount);
EmitSignal(SignalName.PenaltyApplied, amount);
if (energy == 0)
EmitSignal(SignalName.Finished, participantName);
}
}
public partial class Game : Node
{
public override void _Ready()
{
Participant anna = GetNode<Participant>("Anna");
anna.PenaltyApplied += OnPenalty;
anna.Finished += OnFinished;
}
private void OnPenalty(int amount) { }
private void OnFinished(string name) { }
}