티스토리 뷰

728x90

고도 스크립트 개요, 예약어와 연산자, 고도 스크립트 타입과 변수 선언에 이은 글이다.

 

 클래스

고도에서는 스크립트 파일 하나를 기본적으로 하나의 클래스로 간주한다. 단, 이름 없는 클래스인데 해당 파일에 이름을 부여하고 싶다면 class_name 키워드를 사용하여 "class_name 클래스명, 아이콘 경로"의 형식으로 기술할 수 있다. 아이콘 지정은 생략할 수 있다.

위의 그림은 스크립트에 클래스 이름을 부여하면서 아이콘을 지정한 것으로 해당 스크립트를 사용하는 노드의 아이콘이 편집기에서 지정한 것으로 변경된 것을 확인할 수 있다. 아이콘을 지정하지 않으면 상속한 부모 클래스의 아이콘을 표시한다. 

 

고도의 클래스는 변수와 함수를 가질 수 있으며 함수는 static으로 정의해서 인스턴스화 없이도 사용할 수 있지만 변수들은 static으로 지정할 수 없다.

 

 내부 클래스

고도 스크립트 내부에 포함되어 정의하는 클래스로 class 키워드를 사용하여 정의한다.

위의 그림은 Bullet라는 내부 클래스를 정의한 예제로 해당 클래스를 인스턴스화 하려면 클래스명.new()를 사용하면 된다.

 

상속

extends 키워드를 사용하여 클래스를 상속받을 수 있으며, 고도 스크립트에서는 여러 클래스를 상속받는 다중 상속은 지원하지 않는다. 

위의 그림은 글로벌하게 사용할 수 있는 클래스를 상속받은 예제로 Godot API에(편집기에서 F1 키를 눌러서 확인하거나 https://docs.godotengine.org/en/stable/classes/index.html 온라인 문서로 확인할 수 있다) 속한 클래스를 지정하는 경우이다. 또 다른 경우는 프로젝트> 프로젝트 설정 메뉴로 들어가서 [오토로드] 탭에 사용자 스크립트를 싱글톤으로 등록해 놓으면 모든 씬에서 사용하는 글로벌 클래스처럼 사용할 수 있다.

위의 예제는 스크립트 파일을 상속하는 것으로 내부 클래스를 상속받을 때는 "classname". 내부 클래스 명의 형식으로 기술한다.

 

임의의 인스턴스가 특정 클래스를 상속받은 것인지 확인할 때 사용하는 것이 is 연산자다. 위의 예제는 body가 Player 클래스를 상속받은 것인지 확인하는 과정이다.

 

특정한 클래스를 상속받는 클래스에서는 부모 클래스에 있는 동일 이름의 함수를 재정의하여 부모 클래스의 함수를 대체할 수 있다. 이를 오버라이딩한다. 위의 그림에서는 Node2D의 _get_item_rest를 재정의하고 있다. 이처럼 부모 클래스와 자식 클래스에 동일한 이름의 함수가 있을 때 자식 클래스에서 부모 클래스의 함수를 호출할 경우에는 함수 이름 앞에 .을 붙인다. 위의 예제에서는 ._get_item_rest() 라고 호출하면 된다.

 

각 클래스에는 _init, _enter_tree, _exit_tree, _process, _physics_process와 같은 기본 함수들이 있는데, 부모 클래스에 있는 기본 함수들은 자동적으로 호출되므로 자식 클래스에서는 이들을 호출할 필요가 없다. 단, 생성자 함수인 _init의 경우 위의 예제처럼 부모 클래스의 생성자 함수에 인수가 있는 경우에는 자식 클래스 생성자 함수에서 부모 클래스의 생성자로 인수를 넘겨주는 과정이 필요하다. 형식은 "func _init().(cls25d):" 처럼 .(인수)를 추가해 준다.

 

 

 내보내기

클래스 변수 앞에 export 키워드를 붙이면 고도 편집기 인스펙터 창의 스크립트 변수 섹션에서 해당 값을 수정할 수 있게 해 준다. 클래스 자체는 바꾸지 않으면서 인스턴스에만 해당 값을 적용한다. 변수 내보내기를 할 때는 위의 예제처럼 상수로 초기화하거나 export(힌트 표현)와 같이 어떤 타입으로 값을 입력받을지를 알려주어야 한다.

 

위의 그림을 보면 Player 노드를 클릭하면 인스펙터 창에서 내보내기 한 speed를 스크립트 변수 영역에서 수정할 수 있음을 확인할 수 있다. 변경한 내용은 클래스 자체에는 영향을 주지 않고 인스턴스에만 적용된다.

 

위의 예제는 변수 내보내기를 하면서 힌트를 제공한 사례이다. 

 

export(PackedScene) var ball_scene = preload("res://ball.tscn")
export(float) var character_speed = 400.0
export(Vector2) var map_size = Vector2.ONE * 16
export(String, FILE) var scene_to_change_to = null      #파일의 경로를 갖는 문자열
export(String, FILE, "*.json") var dialogue_file             #파일 필터 적용
export(String, DIR) var f                                        #폴더의 경로를 갖는 문자열
export var _enable_debug_collision = true
export(bool) var flip_axis = false
export(String) var action = "ui_up"
export(int, 1, 1000) var player_id = 1                        #1~1000 사이 정수
export(Color, RGBA) var split_line_color = Color.black
export(Color, RGB) var col
export(float, 0, 360, 0.1) var _platform_angle = 0.0       #0~360 사이 실수, 0.1씩 증감
export(Array, NodePath) var spawns = Array()
export(int, "_process", "_physics_prc", "_notif", "none") var update_mode = 0 #문자열 선택 시 0~3 정수로
export(int, "X-up", "Y-up", "Z-up") var look_at_axis = 1

위의 예제는 변수 내보내기를 하면서 다양한 힌트를 제공하고 있는 사례들이다.

 

세터 게터

클래스 내 변수에 대한 쓰기 또는 읽기 접근이 있을 때 호출하는 함수를 세터 게터라 하며 고도에서는 변수 선언 뒤에 setget 키워드를 사용하고 세터 함수명, 게터 함수명을 기술하는 방식으로 적용한다. 세터 또는 게터 하나만을 기술할 수도 있다.

위의 그림은 세터 및 게터를 정의한 예제로 moves_left 변수는 세터와 게터를 모두 정의했지만, player_turn은 세터만을 정의했고, free_tiles는 게터만을 정의했다. 

 

 함수

고도 스크립트의 함수는 func 키워드를 이용해서 정의하며 항상 특정 클래스에 속한다. 내부에 변수를 정의할 수 있으며 함수 파라미터를 var 변수 선언 방식과 같은 방법으로 정의할 수 있다. 동일한 이름의 변수가 있다면 함수 내 로컬 변수, 클래스 변수, 글로벌 변수 순으로 참조 범위를 결정한다.

 

함수 파라미터 또한 변수 선언처럼 기본값을 지정하거나, 특정 타입을 지정하거나 :=로 기본값 대입과 타입 지정을 동시에 할 수도 있다. 기본값을 지정한 파라미터는 함수를 호출하는 쪽에서 해당 파라미터를 지정하지 않아도 지정한 값으로 처리된다. 각 함수는 기본적으로 null을 리턴 하지만 return 키워드를 이용해서 명시적으로 값을 리턴할 수 있다. 함수의 리턴 타입은 위의 그림처럼 "-> 타입"으로 기술할 수 있으며 "-> void"로 기술하면 C/C++ 함수의 의미와 달리 값을 리턴하지 않는다는 의미이다. 만약 void가 아닌 다른 타입으로 "-> 타입" 리턴 타입을 지정하면 return 문으로 반드시 값을 리턴해야 한다. pass 문을 사용하면 간편하게 아무 일도 하지 않는 스터브 함수를 작성할 수 있다.

 

 함수 참조

위의 예제에서 노드.start() 나 new_shake()는 모두 클래스 내의 함수를 호출하는 과정이다. 그런데, 함수 참조는 함수 자체를 인수처럼 사용하는 경우를 위한 것이다.

위의 예제를 보면 현재 노드에 "SetViewMode"라는 함수가 있는지 확인해서 해당 함수가 존재하면 call(함수 이름, 인수)의 형식으로 해당 함수를 호출하고 있다.

 

var my_func = funcref(my_node, "add") if cond == 0 else funcref(my_node, "sub")
my_func.call_func(args)

위의 코드는 조건에 따라 서로 다른 함수 참조를 funcref를 이용해서 변수에 저장했다가 call_func(파라미터)로 호출하는 과정을 보여준다. 위와 같은 함수 참조는 하나의 로직 흐름에 따라 다양한 함수 호출이 필요한 경우 유용하게 활용할 수 있다.

 

정적 함수

함수는 항상 클래스에 포함되므로 함수 호출을 클래스 내부에서 수행할 때는 별 문제가 없지만 클래스 외부라면 클래스의 인스턴스를 통해서 호출해야 한다. 그러나 함수 정의 시 static 키워드를 붙여서 정의하면 정적 함수로 인스턴스 없이 클래스 함수로 직접 호출할 수 있다. 라이브러리 함수 등에서 많이 사용한다.

 

 

 

728x90
댓글
글 보관함
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31