728x90
본 게시글은 고도엔진 공식문서에 작성된 Using signals를 정리하였습니다.
신호(Signal)
- 버튼을 누르는 것과 같은 특정 상황이 발생했을 때 노드가 보내는 메시지
- 게임 오브젝트가 서로 참조하지 않고도 다른 오브젝트의 변화에 반응할 수 있게 해준다.
- 유니티의 이벤트와 유사한 역할을 한다.
씬 설정
- [GodotDoc][Step by step] 3. 첫 번째 스크립트 만들기(C#) 에서 이어서 작업한다.
- 상단 메뉴에서 Scene>New Scene를 선택하여 새로운 씬을 추가한다.
- Scene 도크에서 2D Scene를 선택하여 Node2D 노드가 새로 만든 씬의 루트 노드가 되도록 만든다.
- 이전 작업에서 만들었던
sprite_2d.tscn
씬을 새로 만든 씬의 자식 노드로 배치한다. - [GodotDoc][Step by step] 2. 인스턴스 생성 참고
- Scene 도크에서 루트 노드를 선택한 후, ➕아이콘을 선택하여 새로운 자식 노드를 추가한다.
- Create New Node 팝업창이 열리면 검색창(Search:)에 Button이라고 입력한다.
- Button 노드를 선택한 후 Create 버튼을 선택하여 Button 노드를 추가한다.
- Scene 도크에서 새로 추가된 Button 노드를 선택한다.
- 뷰포트에서 Button 노드의 크기를 조절한다.
- Inspector 도크의 Text 속성 아래있는 텍스트 입력창에 Toggle motion라고 입력한다.
- 작업했던 씬은
node_2d.tscn
으로 저장한다. - FileSytem 도크에서
node_2d.tscn
씬을 우클릭한다. - Scene as Main Scene를 선택하여
node_2d.tscn
씬을 메인 씬으로 설정한다.
에디터에서 시그널 연결
- C#은 GDScript와 달리 시그널을 연결할 때 함수를 자동 생성하지 않기 때문에 시그널과 연결할 함수(메소드)를 직접 정의해야 된다.
MySprite2D.cs
스크립트에OnButtonPressed
메소드를 추가한다.
public void OnButtonPressed()
{
}
- Scene 도크에서 Button 노드를 선택한 후 Inspector 도크 옆에 있는 Node 도크를 선택한다.
- Node 도크에서
pressed()
시그널을 더블 클릭한다. - Connect a Signal to a Method 팝업창이 열리면서 Sprite2D 노드가 자동으로 선택된다.
- 자동으로 선택되지 않았다면 직접 선택한다.
- Receiver Method 아래 텍스트 입력창에
OnButtonPressed
메소드를 입력한다. - Connect 버튼을 선택한다.
- 앞으로 버튼을 누르면
OnButtonPressed
함수가 자동으로 호출된다. OnButtonPressed
함수에 아래 내용을 추가한다.
public void OnButtonPressed()
{
SetProcess(!IsProcessing());
}
SetProcess
에 false를 입력하면IsProcessing
함수는 false를 반환하게 되고, 매 프레임마다_Process
를 호출하지 않아 Sprite2D 노드는 움직이지 않는다.SetProcess
에 true를 입력하면IsProcessing
함수는 true를 반환하게 되고,매 프레임마다_Process
를 호출하여 Sprite2D 노드가 움직인다.- ! 연산자를 이용하면
IsProcessing
의 반대값을 반환하게되어, 버튼을 누를 때마다 Sprite2D 노드의 움직임을 제어할 수 있다.
타이머 추가
- FileSystem 도크에서
spite_2d.tscn
씬을 불러온다. - Scene 도크에서 Sprite2D 노드를 선택한 후 버튼을 추가하였을 때와 동일한 방식으로 Timer 노드를 자식 노드로 추가한다.
- Scene 도크에서 Timer 노드를 선택한다.
- Inspector 도크에서 Autostart 속성 옆의 체크 박스를 체크한다.
sprite_2d.tscn
씬을 저장한다.
코드에서 시그널 연결
- 에디터 대신 코드에서 시그널을 연결할 수도 있다.
MySprite2d.gd
스크립트에 아래 내용을 추가한다.
public override void _Ready()
{
var timer = GetNode<Timer>("Timer");
timer.Timeout += OnTimerTimeout;
}
public void OnTimerTimeout()
{
Visible = !Visible;
}
_Ready
는 노드가 준비 상태가 되었을 때 한번 호출된다.GetNode<Timer>("Timer")
는 자식 노드로 추가했던 Timer 노드를 반환한다.timeout
은 Timer 노드에서 설정한 시간이 되었을 때 동작하는 시그널이다.- 모든 시그널은 C#에서는 이벤트로 정의되기 때문에
+=
연산자를 이용하여 시그널과 메소드를 연결한다. timer.Timeout += OnTimerTimeout
을 입력하면timeout
시그널이 동작하면OnTimerTimeout
함수를 자동 호출하게 된다.Visible
이 true일 경우 노드가 화면에 출력되고, false일 경우 화면에 출력되지 않는다.
커스텀 시그널
- 스크립에서 원하는 시그널을 직접 선언할 수 있다.
MySprite2D.cs
스크립트에서 선언한 메소드 바로 위에 시그널을 선언한다.
[Signal]
public delegate void ProcessEnabledEventHandler();
[Signal]
public delegate void VisiblityChangedEventHandler(bool isVisible);
- C#에서 시그널은 아래 규칙에 맞춰 델리게이트로 선언한다.
- 델리게이트는
Signal
속성을 정의(Attribute)를 정의해야 된다. - 델리게이트의 이름은 반드시 EventHandler로 끝나야 된다.
- 델리게이트는
- 델리게이트를 선언하면 자동으로 생성되는
MySprite2D_ScriptSignals.generated.cs
스크립트에 이벤트와 상수로 자동 선언된다.
- 선언한 시그널은
EmitSignal
메소드를 이용하여 신호를 발생시킨다. MySprite2D.cs
스크립트에서OnButtonPressed
함수와OnTimerTimeout
함수에 각각EmitSignal
메소드를 호출하도록 수정한다.
public void OnButtonPressed()
{
SetProcess(!IsProcessing());
if (IsProcessing())
EmitSignal(SignalName.ProcessEnabled);
}
public void OnTimerTimeout()
{
Visible = !Visible;
EmitSignal(SignalName.VisiblityChanged, Visible);
}
- 추가한 커스텀 시그널들은 다른 노드에 연결하여 사용할 수 있다.
완성된 스크립트
using Godot;
using System;
public partial class MySprite2D : Sprite2D
{
[Signal]
public delegate void ProcessEnabledEventHandler();
[Signal]
public delegate void VisiblityChangedEventHandler(bool isVisible);
int speed = 400;
float angularSpeed = Mathf.Pi;
public MySprite2D()
{
GD.Print("Hello, world!");
}
public override void _Ready()
{
var timer = GetNode<Timer>("Timer");
timer.Timeout += OnTimerTimeout;
}
public override void _Process(double delta)
{
Rotation += angularSpeed * (float)delta;
var velocity = Vector2.Up.Rotated(Rotation) * speed;
Position += velocity * (float)delta;
}
public void OnButtonPressed()
{
SetProcess(!IsProcessing());
if (IsProcessing())
EmitSignal(SignalName.ProcessEnabled);
}
public void OnTimerTimeout()
{
Visible = !Visible;
EmitSignal(SignalName.VisiblityChanged, Visible);
}
}
'Godot' 카테고리의 다른 글
[GodotDocs][Your First 2D Game] 2. 플레이어 씬 제작 (0) | 2024.01.28 |
---|---|
[GodotDocs][Your First 2D Game] 1. 프로젝트 설정 (0) | 2024.01.14 |
[GodotDocs][Step by step] 5. 시그널 사용(GDScript) (2) | 2024.01.04 |
[GodotDocs][Step by step] 4. 플레이어 입력 수신(C#) (2) | 2023.12.29 |
[GodotDocs][Step by step] 4. 플레이어 입력 수신(GDScript) (0) | 2023.12.29 |