Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

여러분의 첫 스크립트 만들기

이번 단원에서는 GDScript를 사용하여 Godot 아이콘이 원을 그리며 회전하는 첫 번째 스크립트를 코딩해 보겠습니다. 소개 <toc-learn-introduction>`에서 :ref:`를 언급했듯이, 당신이 프로그래밍 기초 지식이 있는 상태라고 가정합니다. 편의를 위해, 동일한 동작을 하는 C# 코드가 다른 탭에 있습니다.

이 튜토리얼은 GDScript용으로 작성되었으며, 편의를 위해 각 코드 블록의 다른 탭에 해당 C# 코드가 포함되어 있습니다.

../../_images/scripting_first_script_rotating_godot.gif

더 보기

GDScript의 키워드와 문법에 대해 좀 더 알아보려면 :ref:`GDScript 참조<doc_gdscript>`를 참조하세요.

프로젝트 설정

초기 상태에서 시작하기 위해 새 프로젝트를 만드세요. 당신의 프로젝트에는 하나의 그림이 포함되어야 합니다: 우리가 커뮤니티에서 프로토타이핑에 자주 사용하는 Godot 아이콘입니다.

../../_images/scripting_first_script_icon.svg

게임에 표시하기 위해 Sprite 노드를 만들어야 합니다. 씬 독에서 기타(Other) 노드 버튼을 클릭합니다.

../../_images/scripting_first_script_click_other_node.webp

검색 창에 "Sprite2D"를 입력하여 노드를 필터링하고 Sprite2D를 더블 클릭하여 노드를 만듭니다.

../../_images/scripting_first_script_add_sprite_node.webp

현재 씬 탭에는 Sprite2D 노드만 있어야 합니다.

../../_images/scripting_first_script_scene_tree.webp

Sprite2D 노드에는 표시할 텍스처가 필요합니다. 오른쪽의 인스펙터에서 텍스처 속성에 <비었음>이라고 표시된 것을 볼 수 있습니다. Godot 아이콘을 표시하려면 파일시스템 독에서 icon.png 파일을 클릭하여 텍스처 슬롯으로 드래그하세요.

../../_images/scripting_first_script_setting_texture.webp

참고

뷰포트에 이미지를 드래그 앤 드롭하여 Sprite2D 노드를 자동으로 만들 수 있습니다.

그런 다음 뷰포트에서 아이콘을 클릭하고 드래그하여 게임 뷰 중앙에 배치합니다.

../../_images/scripting_first_script_centering_sprite.webp

새 스크립트 만들기

새 스크립트를 생성하고 노드에 연결하려면 씬 독에서 Sprite를 마우스 오른쪽 버튼으로 클릭하고 "스크립트 연결"을 선택하세요.

../../_images/scripting_first_script_attach_script.webp

Attach Node Script 창이 나타납니다. 이는 스크립트의 언어와 파일 경로, 기타 옵션 중에서 선택할 수 있도록 합니다.

초기 상태의 파일로 시작하려면 템플릿을 '기본값'에서 '비어 있음'으로 변경하세요. 다른 옵션은 기본으로 두고 생성 버튼을 클릭하여 스크립트를 생성합니다.

../../_images/scripting_first_script_attach_node_script.webp

참고

C# 스크립트 이름은 클래스 이름과 일치해야 합니다. 이 경우, 파일 이름을 MySprite2D.cs로 지정해야 합니다.

스크립트 작업공간은 새 Sprite.gd 파일이 열려 있고 다음 코드 줄이 나타나야 합니다:

extends Sprite2D

모든 GDScript 파일은 암시적으로 클래스입니다. extends 키워드는 이 스크립트가 상속하거나 확장하는 클래스를 정의합니다. 지금 예시에서는 Sprite``입니다. 즉, 스크립트는 ``Node2D, CanvasItemNode2D, CanvasItem``Node 등의 확장되는 클래스를 포함하여 Sprite 노드의 모든 속성과 기능에 접근할 수 있습니다. ``.

참고

GDScript에서 extends 키워드가 있는 줄을 생략하면 클래스는 Godot가 애플리케이션의 메모리를 관리하는 데 사용하는 :ref:`Reference <class_Reference>`를 암시적으로 확장합니다.

상속된 속성에는 노드의 ``텍스처``와 같이 인스펙터 독에서 볼 수 있는 속성이 포함됩니다.

참고

기본적으로 인스펙터는 노드의 속성을 "Title Case"(공백으로 구분되며 대문자로 시작하는 단어 형태)로 표시합니다. GDScript 코드에서 이러한 속성은 "snake_case"(밑줄로 구분되며 소문자로 이루어진 단어 형태)로 표기됩니다.

인스펙터에서 속성 이름에 마우스 커서를 올리면 속성에 대한 설명과, 코드 상에서의 식별자를 볼 수 있습니다.

Hello, friend!

우리 스크립트는 현재 아무것도 하지 않습니다. 시작으로 하단의 Output 패널에 "Hello, world!"라는 텍스트를 출력해 보겠습니다.

다음 코드를 스크립트에 추가하세요:

func _init():
    print("Hello, world!")

내용을 분석해 봅시다. func 키워드는 _init이라는 이름의 새로운 함수를 정의합니다. 이는 우리 클래스 생성자에서 사용하는 특별한 이름입니다. 이 함수를 정의하면 엔진은 메모리에 생성된 모든 개체나 노드에 대해 _init()를 호출합니다.

참고

GDScript는 들여쓰기 기반의 언어입니다. print()가 작성된 라인의 시작 부분의 탭은 코드가 동작하기 위해 반드시 필요합니다. 이를 생략하거나 줄을 알맞게 들여쓰지 않으면 편집기에서 해당 항목을 빨간색으로 강조 표시하고 다음과 같은 오류 메시지를 표시합니다:"들여쓰기 된 블록이 필요합니다".

아직 저장하지 않았다면 씬을 저장한 다음 F6`(macOS에서는:kbd:`Cmd + R)을 눌러 실행하세요. 하단의 Output 패널을 살펴보세요. "Hello, world!"가 표시되어야 합니다.

../../_images/scripting_first_script_print_hello_world.webp

_init() 함수를 삭제해 extends Sprite 줄만 남깁니다.

되돌아보기

이제 노드를 움직이고 회전시킬 차례입니다. 이를 위해 스크립트에 두 개의 멤버 변수, 즉 초당 픽셀 이동 속도와 초당 라디안 각속도를 추가하겠습니다.

var speed = 400
var angular_speed = PI

멤버 변수는 스크립트 상단 부근의 "extends" 줄 보다는 뒤에, 함수 보다는 앞에 위치합니다. 이 스크립트가 붙여진 모든 노드 인스턴스는 speedangular_speed 속성의 복사본을 갖게 됩니다.

참고

Godot에서 각도는 기본적으로 라디안으로 동작하지만, 각도를 도 단위로 계산하는 것을 선호하는 경우 사용 가능한 내장 함수와 속성도 있습니다.

아이콘을 이동하기 위해서는, 게임 루프에서 매 프레임마다 아이콘의 위치와 방향을 업데이트해야 합니다. 이를 위해 Node 클래스의 가상 함수인``_process()`` 함수를 사용할 수 있습니다. Node 클래스를 확장하는 클래스(Sprite 등)에서 정의하면 Godot는 매 프레임마다 함수를 호출하고, 마지막 프레임 이후 경과된 시간인 ``delta``라는 인수를 전달합니다.

참고

게임은 초당 많은 이미지(각각을 프레임이라 부름)를 렌더링하는 방식으로 작동하며, 반복해서 동작합니다. 우리는 초당 프레임 수(FPS)로 게임이 이미지를 생성하는 속도를 측정합니다. 대부분의 게임은 60FPS를 목표로 하지만 느린 모바일 장치에서는 30FPS, 가상 현실 게임에서는 90~240FPS와 정도의 수치를 볼 수 있습니다.

엔진과 게임 개발자는 일정한 시간 간격으로 게임 세계를 업데이트하고 이미지를 렌더링하기 위해 최선을 다하지만, 프레임 렌더링 시간에는 항상 작은 차이가 있습니다. 이것이 바로 엔진이 우리에게 델타 시간 값을 제공하여 움직임을 프레임 속도와 독립적으로 만드는 이유입니다.

스크립트 하단에, 아래와 같은 함수를 정의합니다:

func _process(delta):
    rotation += angular_speed * delta

func 키워드는 새로운 함수를 정의합니다. 이 키워드 뒤에는 함수의 이름과 인수를 괄호 안에 적어야 합니다. 콜론으로 정의를 끝내고, 이후의 들여쓰기 된 블록은 함수의 내용이나 명령입니다.

참고

_init()과 마찬가지로 _process()가 밑줄로 시작한다는 걸 주목하세요. 관례적으로, Godot의 가상 함수, 즉 엔진과 통신하기 위해 오버라이딩 할 수 있는 내장 함수는 밑줄로 시작합니다.

함수 내부의 rotation += angular_speed * delta 줄은 매 프레임마다 스프라이트의 회전을 증가시킵니다. 여기서 rotation``은 ``Sprite``가 상속하는 ``Node2D 클래스에서 상속된 프로퍼티입니다. 이 프로퍼티는 노드의 회전을 제어하며 라디안(radians)으로 작동합니다.

코드 편집기에서, position, rotation 또는 ``_process``와 같은 내장된 속성 혹은 함수 위에서 Ctrl + 클릭을 하면 관련된 문서가 새로운 탭으로 나타납니다.

씬을 실행하여 Godot 아이콘이 제자리에서 돌아가는 것을 확인하세요.

../../_images/scripting_first_script_godot_turning_in_place.gif

참고

C#에서 _Process()가 받는 delta 인수가 double 형식인 것에 주목하세요. 따라서 회전에 적용할 때 이를 ``float``로 변환해야 합니다.

앞으로

이제 노드를 이동시켜 보겠습니다. 새 줄이 이전 줄과 같은 방식으로 들여쓰기 되도록 유의하며 _process() 함수에 다음 두 줄을 추가합니다.

var velocity = Vector2.UP.rotated(rotation) * speed

position += velocity * delta

이미 살펴보았듯이 var 키워드는 새로운 변수를 정의합니다. 이를 스크립트 상단에 넣으면, 클래스의 속성을 정의합니다. 함수 내부에서는 지역 변수(함수 범위 내에서만 존재)를 정의합니다.

방향과 속도를 모두 나타내는 2D 벡터인 'velocity'라는 지역 변수를 정의합니다. 노드가 앞으로 이동하도록 하려면 위쪽을 가리키는 벡터인 Vector2 클래스의 상수인 Vector2.UP에서 Vector2.rotated() 메서드를 호출하여 이를 회전시킵니다. Vector2.UP.rotated(rotation)``라는 표현은 아이콘을 기준으로 앞으로 향하는 벡터입니다. ``speed 속성을 곱하면 노드를 앞으로 이동하기 위한 속도가 적용됩니다.

노드의 positionvelocity * delta를 더하여 이동합니다. position 자체는 2D 벡터를 나타내는 Godot에 내장된 타입인 Vector2 타입입니다.

씬을 실행하여 Godot 머리가 원을 그리며 움직이는 것을 확인하세요.

../../_images/scripting_first_script_rotating_godot.gif

참고

지금의 노드 이동은 벽이나 바닥과의 충돌을 고려하지 않고 있습니다. 2D 게임 시작하기에서는 콜리전을 감지하면서 물체를 움직이는 또 다른 접근 방식을 배워볼 것입니다.

우리 노드는 현재 스스로 움직입니다. 다음 파트 :ref:`doc_scripting_player_input`에서는 플레이어 입력을 사용하여 제어합니다.

GDScript 예제

참조용 전체 Sprite.gd 파일은 다음과 같습니다.

extends Sprite2D

var speed = 400
var angular_speed = PI


func _process(delta):
    rotation += angular_speed * delta

    var velocity = Vector2.UP.rotated(rotation) * speed

    position += velocity * delta