본문 바로가기
Programming/Godot

Godot 엔진 시작하기 - 스크립팅 2

by Wilkyway 2022. 1. 12.
반응형

스크립팅(계속)

Processing

대부분의 스크립트는 매 프레임에서 처리되어야 합니다. 처리에는 idle(유휴상태) 처리와 physics(물리) 처리의 두 가지 유형이 있습니다.

Idle 처리는 Node._process() 메서드가 스크립트에서 발견되면 활성화됩니다. Node.set_process() 함수로 켜고 끌 수 있습니다. 이 메서드는 프레임이 그려질 때마다 호출됩니다.

func _process(delta):
    # Do something...
    pass

_process() 함수가 호출 빈도는 실행 중인 애플리케이션의 FPS(초당 프레임 수)에 따라 다릅니다. 이 비율은 실행 시점마다, 또는 장치에 따라 다를 수 있습니다.

delta매개변수에는 _process()를 호출한 이전 시점부터 경과된 시간(초)이 부동 소수점 숫자로 포함됩니다.

이 매개변수는 게임의 FPS에 관계없이 항상 동일한 시간이 소요되도록 하는 데 사용할 수 있습니다.

예를 들어, 움직임 속도를 프레임 속도와 상관없이 일정하게 만들기 위해 움직임에 시간 델타를 곱하는 경우가 많습니다.

_physics_process() 함수도 비슷하지만 캐릭터 제어와 같이 각 물리 단계 전에 발생해야 하는 프로세스에 사용해야 합니다. 즉, 좀 더 정확한 간격의 시간에 실행할 필요가 있을 때 이 함수를 사용합니다. 기본적으로 초당 60회입니다. Physics -> Common -> Physics Fps 아래의 Project Settings 메뉴에서 간격을 변경할 수 있습니다.

_process()은 physics와 동기화되지 않습니다. 프레임 속도는 하드웨어 및 게임 최적화 등에 따라 모두 다릅니다. 실행은 single-threaded 게임에서 물리 단계 후에 수행됩니다.

_process() 함수가 작동 중인지 다음 스크립트로 간단히 확인해보겠습니다. 

extends Label

var accum = 0

func _process(delta):
    accum += delta
    text = str(accum) # 'text' is a built-in label property.

매 프레임마다 값이 증가되는 카운터가 표시됩니다. 

그룹

 Godot의 그룹은 다른 소프트웨어에서 볼 수 있는 태그와도 유사한 개념입니다. 노드는 복수의 그룹에 추가할 수 있습니다.  그룹 추가 첫번째 방법은 UI의 Node 패널 아래의 Groups 버튼을 사용하여 지정하는 방법입니다.

그리고 두 번째 방법은 코드에서입니다. 

func _ready():
    add_to_group("enemies")

SceneTree.call_group() 함수는 group 과 액션함수를 연결하는 함수입니다. 아래 코드는, 플레이어가 비밀 기지에 몰래 잠입한 것이 발견되면 모든 적에게 알람을 울리는 예시 코드입니다.

func _on_discovered(): # This is a purely illustrative function.
    get_tree().call_group("enemies", "player_was_discovered")

enemies그룹의 모든 멤버에 대해 player_was_discovered함수를 호출합니다 .

SceneTree.get_nodes_in_group() 함수는 enemies 노드 목록을 가져옵니다.

var enemies = get_tree().get_nodes_in_group("enemies")

SceneTree 클래스에는 장면, 해당 노드 트리 및 노드 그룹과의 상호 작용과 같은 많은 메서드를 제공합니다. 이를 통해 장면전환, 게임 재 로딩, 게임 종료, 일시 중지/해제 등을 쉽게 구현할 수 있습니다.

재정의 가능한 함수

노드에는 아래와 같이 재정의 가능한 함수들이 존재합니다.

func _enter_tree():
    # 노드가 Scene Tree에 들어가면 활성화됩니다.
    # 이 함수가 호출됩니다. 하위 노드는 아직 Scene Tree에 들어가지 않았습니다.
    # 대부분의 경우 _ready()를 사용하는 것이 좋습니다.
    pass

func _ready():
    # _enter_tree이후에 들어갑니다. 모든 하위 노드들이 Scene Tree에 들어갔으며
    # active상태임을 보장합니다.
    pass

func _exit_tree():
    # 노드가 Scene Tree를 나갈 때 이 함수가 호출됩니다.
    # 모든 하위 노드들은 Scene Tree나갔으며 모두 비활성화되었습니다    
    pass

func _process(delta):
    # 매 프레임마다 호출됨
    pass

func _physics_process(delta):
    # 매 물리프레임마다 호출됨
    pass

 

노드 생성

코드에서 노드를 생성하려면 다른 클래스 기반 데이터 유형과 마찬가지로 .new() 메서드를 호출합니다. 

var s
func _ready():
    s = Sprite.new() # 새 sprite노드 생성
    add_child(s) # 이 노드에 자식 노드로 추가.

노드를 삭제하려면 장면 내/외부에 관계없이 free() 함수를 사용합니다.

func _someaction():
    s.free() # 장면에서 노드를 즉시 제거/해제.

노드가 해제되면 모든 자식 노드도 해제됩니다. 이 때문에 노드 수동 삭제가 간단합니다. 기본 노드를 해제하면 하위 트리의 다른 모든 항목이 함께 사라집니다.

Signal 또는 함수 호출로 인해 "Blocked" 노드를 삭제하려는 시도가 의도치 않게 발생할 수 있습니다. 이 경우 게임이 중단되고, 디버거에서 경고를 보내줄 수도 있습니다. 노드를 삭제하는 가장 안전한 방법은 Node.queue_free() 함수를 사용하는 것 입니다. idle 상태에서 노드가 안전하게 지워집니다.

func _someaction():
    s.queue_free() # 씬에서 안전하게 삭제/해제 가능할 경우 수행

씬 인스턴싱 (Instancing Scenes)

코드에서의 씬 인스턴싱은 두단계로 수행됩니다. 첫번째는 씬 로딩입니다.

var scene = load("res://myscene.tscn") # 스크립트가 인스턴싱(수행)되면 불러옴.

preload는 구문 분석 타이밍에 발생하므로 더 편리할 수 있습니다(GDScript만 해당):

var scene = preload("res://myscene.tscn") # 스크립트 구문분석 타이밍에 불러옴

그러나 씬은 아직 노드가 아닙니다. PackedScene 이라는 특수 리소스에 Pack되어 있습니다. 실제 노드를 생성하려면 PackedScene.instance() 함수 를 호출해야 합니다. 그러면 활성 씬에 추가할 수 있는 노드 트리가 반환됩니다.

var node = scene.instance()
add_child(node)

이 2단계 프로세스의 장점은 패킹된 장면을 로드하고 사용할 준비가 된 상태에서, 원하는 만큼 많은 인스턴스를 생성할 수 있다는 것입니다. 이는 활성 씬에서 여러 적, 총알 등을 빠르게 인스턴스화하는 데 유용합니다.

스크립트를 클래스로 등록

Godot에는 "스크립트 클래스" 기능이 있습니다. 파일을 직접 로드하여 명명되지 않은 스크립트에만 액세스할 수 있습니다. 편집기에서 class_name키워드 다음에 클래스 이름을 사용하여 타입으로 등록할 수 있습니다. 그런 다음 쉼표 뒤에 PNG 또는 SVG 의 아이콘 이미지 경로를 추가합니다. (최소 16×16, 32×32 권장). 그러면 노드 또는 리소스 생성 대화 상자에서 추가한 새로운 타입을 찾을 수 있습니다. (에디터 재시작 필요)

extends Node

# Declare the class name here
class_name ScriptName, "res://path/to/optional/icon.svg"

func _ready():
    var this = ScriptName           # reference to the script
    var cppNode = MyCppNode.new()   # new instance of a class named MyCppNode

    cppNode.queue_free()

Godot 3.1참고:

  • GDScript 및 NativeScript(C++ 및 기타 GDNative 기반 언어)만 스크립트 클래스 등록가능
  • GDScript만 스크립트 클래스의 전역 변수 생성가능
반응형

댓글