C# 기능

이 페이지는 C#과 Godot에서 일반적으로 사용되는 기능과 어떻게 이 둘이 함께 사용되는 지에 대한 개요입니다.

형 변환(Type conversion)과 캐스팅(casting)

C#은 정적으로 타입형 언어입니다. 그러므로 다음을 할 수 없습니다:

var mySprite = GetNode("MySprite");
mySprite.SetFrame(0);

Node 인스턴스를 반환하는 GetNode() 메서드. Sprite의 경우, 원하는 파생 타입을 명시적으로 변환해야 합니다.

이를 위해, C#에서는 다양한 설정이 있습니다.

캐스트(Cast)와 타입 체크(Type Check)하기

반환된 노드를 Sprite로 캐스트 할 수 없는 경우 InvalidCastException을 발생시킵니다. 실패하지 않는다고 확신하면 as 연산자 대신에 그것을 사용할 것입니다.

Sprite mySprite = (Sprite)GetNode("MySprite");
mySprite.SetFrame(0);

AS 연산자 사용하기

노드가 Sprite로 캐스트 될 수 없다면 as 연산자는 null을 반환합니다, 그렇기 때문에 값 타입과는 함께 사용될 수 없습니다.

Sprite mySprite = GetNode("MySprite") as Sprite;
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

일반 메서드 사용하기

일반 메서드는 이 타입 변환을 투명하게 만들기 위해 제공됩니다.

GetNode<T>()은 반환하기 전에 노드를 캐스트 합니다. 노드가 원하는 타입으로 캐스트 되지 않는다면 InvalidCastException을 발생시킵니다.

Sprite mySprite = GetNode<Sprite>("MySprite");
mySprite.SetFrame(0);

GetNodeOrNull<T>()as 연산자를 사용하고 노드가 원하는 타입으로 캐스트 되지 않는다면 null을 반환합니다.

Sprite mySprite = GetNodeOrNull<Sprite>("MySprite");
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);

IS 연산자를 사용하여 타입 체크하기

노드가 Sprite로 캐스트 되도록 체크하기 위해, is 연산자를 사용할 수 있습니다. Sprite가 캐스트 되지 않는다면 is 연산자는 거짓을 반환하고, 그렇지 않으면 참을 반환합니다.

if (GetNode("MySprite") is Sprite)
{
    // Yup, it's a sprite!
}

더 많은 고급 타입 체크하기의 경우, 패턴 일치에서 찾아볼 수 있습니다.

C# 시그널

완전한 C# 예제를 위해, 단계별 Scripting languages 튜토리얼에서 시그널 다루기를 참고하세요.

C#에서 시그널 선언은 델리게이트(delegate)에서 [Signal] 속성으로 됩니다.

[Signal]
delegate void MySignal();

[Signal]
delegate void MySignalWithArguments(string foo, int bar);

위 시그널들은 에디터 혹은 코드 내에서 Connect 메소드를 이용해 연결할 수 있습니다. 에디터에서 시그널을 연결할 때, 프로젝트 구성물(assembly) 를 다시 빌드해야 추가된 시그널을 확인할 수 있습니다. 에디터 창 우측 상단 모퉁이의 "Build" 버튼을 눌러 직접 빌드할 수 있습니다.

public void MyCallback()
{
    GD.Print("My callback!");
}

public void MyCallbackWithArguments(string foo, int bar)
{
    GD.Print("My callback with: ", foo, " and ", bar, "!");
}

public void SomeFunction()
{
    instance.Connect("MySignal", this, "MyCallback");
    instance.Connect(nameof(MySignalWithArguments), this, "MyCallbackWithArguments");
}

EmitSignal 메서드로 시그널을 방출할 수 있습니다.

public void SomeFunction()
{
    EmitSignal(nameof(MySignal));
    EmitSignal("MySignalWithArguments", "hello there", 28);
}

nameof 키워드로 항상 시그널 이름을 참조할 수 있다는 것을 명심하세요 델리게이트 자체에 적용됨).

It is possible to bind values when establishing a connection by passing a Godot array.

public int Value { get; private set; } = 0;

private void ModifyValue(int modifier)
{
    Value += modifier;
}

public void SomeFunction()
{
    var plusButton = (Button)GetNode("PlusButton");
    var minusButton = (Button)GetNode("MinusButton");

    plusButton.Connect("pressed", this, "ModifyValue", new Godot.Collections.Array { 1 });
    minusButton.Connect("pressed", this, "ModifyValue", new Godot.Collections.Array { -1 });
}

시그널은 매개변수를 지원하고, 모든 내장 타입의 값들과 Godot.Object에서 파생된 클래스들을 묶습니다. 결과적으로, 모든 NodeReference는 자동으로 호환될 것이지만, 맞춤 데이터 오브젝트는 Godot.Object나 그 하위 클래스에서 확장해야 할 것입니다.

public class DataObject : Godot.Object
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

마침내, 시그널은 AddUserSignal로 호출하는 것으로 생성될 수 있지만, 시그널을 사용하기 전에 실행되어야 한다는 것을 명심하세요 (ConnectEmitSignal로 말이죠).

public void SomeFunction()
{
    AddUserSignal("MyOtherSignal");
    EmitSignal("MyOtherSignal");
}

전처리기 지시문

Godot은 컴파일하는 환경에 따라 C# 코드를 변경할 수 있도록 여러 전처리기 지시문을 제공합니다.

참고

Godot 3.2 버전 이전에 프로젝트를 생성했다면, csproj 파일을 수정하거나 재생성해야 이 기능(<DefineConstants> 를 3.2 이후의 프로젝트와 비교해보십시오)을 사용할 수 있습니다.

예제

예를 들어, 다음과 같이 플랫폼에 따라 코드를 변경할 수 있습니다:

    public override void _Ready()
    {
#if GODOT_SERVER
        // Don't try to load meshes or anything, this is a server!
        LaunchServer();
#elif GODOT_32 || GODOT_MOBILE || GODOT_WEB
        // Use simple objects when running on less powerful systems.
        SpawnSimpleObjects();
#else
        SpawnComplexObjects();
#endif
    }

혹은 여러분의 코드를 실행하는 엔진의 상태를 확인하는데 사용할 수도 있습니다. 크로스-엔진 라이브러리를 제작하는데 유용한 기능입니다:

    public void MyPlatformPrinter()
    {
#if GODOT
        GD.Print("This is Godot.");
#elif UNITY_5_3_OR_NEWER
        print("This is Unity.");
#else
        throw new InvalidWorkflowException("Only Godot and Unity are supported.");
#endif
    }

모든 지시문

  • GODOT 은 항상 Godot 프로젝트를 정의합니다.

  • 컴퓨터 환경이 64-bit인지 32-bit인지에 따라서 GODOT_64GODOT_32 중 하나가 정의됩니다.

  • 사용중인 운영체제의 종류에 따라서 GODOT_X11, GODOT_WINDOWS, GODOT_OSX, GODOT_ANDROID, GODOT_IOS, GODOT_HTML5, 또는 GODOT_SERVER 중 하나가 정의됩니다. 위 이름들은 후에 변경될 수 있습니다. 이들은 OS 싱글턴의 get_name() 메서드로 생성될 수 있지만, 메서드가 반환하는 모든 OS에서 Mono 버전 Godot이 실행될 수 있는 것은 아닙니다.

내보내기 를 할 때, 내보내기 기능에 따라서 아래의 것들이 정의될 수 있습니다:

  • 플랫폼에 따라서 GODOT_PC, GODOT_MOBILE, 또는 GODOT_WEB 중 하나가 정의됩니다.

  • Android 아키텍처에 따라서 GODOT_ARM64_V8AGODOT_ARMEABI_V7A 중 하나가 정의됩니다.

  • iOS의 아키텍처에 따라서 GODOT_ARM64GODOT_ARMV7 중 하나가 정의됩니다.

  • 텍스처 압축 타입에 따라서 GODOT_S3TC, GODOT_ETC, 그리고 GODOT_ETC2 가 정의될 수 있습니다.

  • 내보내기 메뉴에서 추가된 커스텀 기능은 다음과 같이 대문자화 된 후 접두사가 붙습니다: foo -> GODOT_FOO.

예제 프로젝트를 확인하려면 OS 테스트 데모를 확인하세요: https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test