기본 콘텐츠로 건너뛰기

템플릿 코드 살펴보기

템플릿 코드 살펴보기

프로젝트 템플릿을 설치 했고, VSCode를 위한 확장 프로그램도 잘 설정을 완료해서 이제 실행 및 디버깅까지 되는 것을 확인했다. 그럼, 이제 코드가 어떻게 생겼는지 한번 살펴볼 차례다.

폴더 구조

위와 같이 루트에 Cargo.toml 이 있고, src 폴더에 lib.rs, game.rs 파일이 있고, tests 폴더에 기본으로 생성된 gd_test_main.rs 파일이 있는 것을 볼 수 있다.

Cargo.toml

기본으로 패키지 정보와 라이브러리 그리고 의존관계가 있는 라이브러리 정보가 들어 있다. 잘 봐야 하는 부분은 의존성 부분인데, gdnative 버젼이 "0.9.3"으로 되어 있다. 하지만, 깃헙에 있는 프로젝트 readme.md 파일에 있는 Engine compatibility를 보면 Godot 3.2 버젼부터 모든 릴리즈된 마이너 버젼과 호환성을 유지한다고 되어 있고, Godot 3.4 버젼은 별다른 설정없이 사용 가능하다고 되어 있다. 하지만 아래쪽 Usage 항목을 보면 최신 마스터 버젼과 Godot 3.4버젼을 사용하는 것을 권장 하고 있으며, 이 때 의존성 항목에서 gdnative 의 벼전을 지정하는 대신 아래와 같이 git 주소를 적는 것으로 대신하면 된다.
앞선 템플릿에 적혀있는대로 사용하는 것은 Godot 3.2.3-stable 버젼을 사용할 때만 유용하다.
즉, Godot을 최신버젼으로 사용하려면 gdnative 버젼을 명시하는 대신 git 주소를 사용하고, 좀 더 안정적으로 사용하고 싶은 경우에는 gdnative 버젼을 0.9.3으로 명시하고, Godot 엔진의 버젼도 3.2.3-stable 버젼을 사용하면 된다.

lib.rs

우선, main.rs 대신 lib.rs가 있으므로 이 rust 프로젝트가 라이브러리 프로젝트라는 것을 알 수 있다. 
하는 일을 보면, 11라인에서 godot_init! 매크로를 통해 init 함수를 넘겨주고있다. 이 init함수 안에서는 InitHandle에 있는 add_class 매서드를 통해 1라인에서 선언한 game 모듈에 있는 Game이라는 구조체 타입을 념겨주는고 있는 것을 볼 수 있다.
즉, 이 러스트 프로젝트 폴더에 있는 내용은 이 파일에 있는 init 함수안에서 add_class를 통해 외부로 노출되어 Godot에서 이용할 수 있게되는 것을 알 수 있다. 현재는 Game 모듈만 셈플로 들어 있지만, 다른 모듈을 작성하게 되면 추가로 여기에 등록만 하면 Godot 에서 사용할 수 있게 되는 것 이다.

game.rs

Rust로 작성된 godot script는 어떤 모습일지 가장 궁금했던 파일이다. GDScript에서 작성하던 것을 rust 코드에서는 어떻게 작성해야 할지, 어떤 제약이 있는지, 어떤 장점이 있는지 궁금했다.

일단, 몇 줄 되지는 않지만 확실히 GDScript 보다는 많이 복잡하고 어려워 보인다. 전체적으로 훑어보면, 우선 파일 가장 위쪽에 어떤 네임스페이스를 사용하는지 적혀 있다. 그리고, 바로 아래에 Game 구조체의 선언이 보이고, 그 아래에 구조체의 메서드들이 impl 블럭으로 구현되어 있는 구조를 가지고 있다. 전체적으로 일반적인 rust 구조체 구현 형식인 것을 알 수 있다.

Game 선언 앞쪽에 있는 derive 매크로들

  • #[derive(NativeClass)] 
    Game 구조체(class)가 NativeClass의 파생형임을 알려준다.
  • #[inherit(Node)]
    Game 구조체가 Godot의 Node 클래스를 상속받은 클래스 임을 알려준다.
  • #[register_with(Self::register_builder)]
    클래스가 등록될 때 어떤 함수를 컬백으로 등록할지 알려주는 애노테이션. 여기서는, register_builder라는 이름을 가진 메서드가 컬백으로 등록된다.

Game 구조체(클래스) 선언

pub 이 앞쪽에 붙어서 외부에 노출되어 Godot에서 사용할 수 있는 구조체임을 알 수 있다. 내부에 name 이라는 스티링 타입 필드가 있다.

메서드 구현부분

  • register_builder
    앞에서 컬백으로 등록한 메서드다. 이 구조체가 Godot에 등록될 때 호출되게 된다. gdnative crate 안에 있는 godot_print! 메크로를 이용해 "Game builder is registered!"라는 메시지를 출력하고 있다. Godot-editer의 output 텝에서 볼 수 있다.
  • new
    Godot의 _init 메서드에 해당하는 생성자 메서드이다. Game 구조체의 name필드를 ""으로 초기화 하고, 새로운 Game구조체의 인스턴스를 반환한다.
  • _ready
    Godot Node의 _ready에 해당하는 메서드. node와 자식 node가 scene tree에 진입을 완료 했을 때 호출된다(자세한 내용은 Godot의 Node 문서 참조). 주로 Node에서 초기화 작업이 필요할 때 이곳에 해당 내용을 넣으면 된다. 예제에서는 Game구조체를 생성할 때 빈 문자열로 지정된 name필드에 "Game"이라는 스트링을 넣어준 후, 메시지를 출력하고 있다.
    함수자체에 unsafe라고 선언이 되어 있는데 현재 들어있는 내용에는 unsafe한 내용이 없기 때문에 삭제해도 정상적으로 동작 한다. 개인적으로는 함수에 unsafe를 넣기 보다는 unsafe한 동작을 할 때 그 곳에섬 unsafe 블럭을 넣는게 더 적절하지 않을까 하는 생각이다.
  • _process
    Godot Node의 _process에 해당하는 메서드이다. main loop의 매 processing step마다 호출되는 메서드다. 매 프레임마다 호출되기 때문에 delta 값은 일정하지 않다. 따라서 일정한 동작을 시키려면, delta값을 이용해 적절한 계산을 통해 코드를 작성해야 한다. 역시 자세한 내용은 Godot의 Node 문서를 참조하면 된다.
템플릿으로 제공되는 보일러플레이트 코드를 살펴봤다. 생각보다 많은 예제가 들어있지는 않지만 작은 시작을 하는데는 충분한 내용이 들어 있는 것 같다. 이제 다른 셈플 코드나 예제등을 살펴보면서 좀 더 다양한 경우, 예를 들어 시그널 처리, 자식 노드 처리, 동적으로 노드 읽어오기 등등을 어떻게 처리 하는지 알아 보면 될 것 이다.

댓글

이 블로그의 인기 게시물

[C#] 자동으로 특정 팝업창 닫기

[C#] 자동으로 특정 팝업창 닫기 Windows UI 테스트 혹은 자동화 작업을 할 때, 특정 윈도우창 혹은 팝업창이 뜨는 것을 인지 하고, 내용을 얻거나 버튼을 누르려면,  System.Windows.Automation 의 AddAutomationEventHandler 를 사용하면 된다. Hook 설정 4 번째 라인에서 WindowOpendEvent를 설정 함 으로써, 창이 열릴 때 hook이 걸린다. 7 번째 라인에서 event handler를 등록 한다. Event Handler 설정 8 번째 라인에서 element의 이름이 내가 찾는 이름인지 비교한다. 15번째 라인에서 팝업창의 내용을 출력 한다. 22번째 라인에서 팝업창의 자식 element중에 "N" 문자가 포함된 것 즉, 아니오 버튼을 찾는다. 24~25번째 라인에서 버튼을 누르는 동작을 수행 한다.

Godot-Rust 게임 아키텍처

이 글은 The godot-rust Book 의 Game architecture 에 나온 내용을 다시 정리한 내용이다. godot-rust는 사용자에게 많은 자유를 주고 있기 때문에 어떤 패턴을 강요하지 않는다. GDScript나 Rust를 얼마나 많이 사용할 지는 순전히 사용자에게 달려 있다. GDScript와 Rust 의 장단점 비교 GDScrip 장점: 고도 에디터와 잘 통합되어 있어 빠른 프로토타이핑이 가능하다. 단점: 타입 시스템이 제한적이고 리펙터링은 수동으로 해야 한다. 종속성 관리가 없다. Rust 장점: 성숙한 도구와 에코시스템에 기반한 타입 안정성, 성능, 확정성에 중점을 두고 있다. 단점: 언어가 좀 더 복잡하고 제약이 강하며, Godot과 연관된 부분은 장황해 지는 경향이 있다. 즉, GDScript는 Godot엔진과 잘 통합되어 있고 쉽고 빠른 코드작성이 가능한 반면, 타입 안정성 부족으로 인해 코드의 규모가 커진 경우 안정적인 관리가 어렵고 속도가 느린 단점이 있다. 다음은 Godot 엔진에 Rust를 사용하는 방법들에 대한 몇가지 예시들 이다. Godot game + Rust module 이구조는 대부분의 게임은 Godot engine과 GDScript로 만들고 일부 모둘만 Rust를 사용해 개발 하는 방법이다. Rust로 개발할 만한 부분을 예로 들면 다음과 같은 경우를 들 수 있다. GDScript가 충분히 빠르지 않은데, 해당 코드가 성능에 민감한 경우. pathfinding, AI, 물리 관련과 같은 Rust기반 라이브러리를 사용하고 싶은 경우. GDScript로는 관리하기 어려운 매우 복잡한 코드블럭이 있는 경우. 이런 경우들에서는 딱 원하는 만큼만 Rust를 이용해 작성할 수 있다. godot-rust 는 필요한 만큼만 GDScript에 노출되도록 할 수 있다. Rust 코드에서 Godot 코드를 호출하는 경우는 없는 경우다. 이런 경우 장단 점은 다음과 같다. 장점 Godot 코드가 이미 있는 경우, 시작하기 쉽다....

Dodge The Creep - [1]

Dodge The Creep - [1] 환경 설정 Godot 공식 문서에 나와있는 2D 튜토리얼인 Dodge The Creep 게임을 Rust를 이용해서 따라 만들어 보자. 템플릿 복사 및 실행 우선 프로젝트 셋업을 해야 한다. 이 부분은 Rust를 이용한다고 해도 크게 바뀌는 부분은 없다. 하지만, GDScript를 이용한다면, Godot Editor를 이용해서 처음부터 하면 되겠지만, Rust를 이용하기 때문에 우선 cargo를 이용해 기본 프로젝트 template를 만들고 난 후, 생성된 godot 폴더에서 프로젝트 설정을 수정하도록 한다. $ cargo generate  - - git https: / / github.com / godot - rust / godot - rust - template  - - name dodge - the - creep - rust $ cd dodge-the-creep-rust $ cargo make run Colored by Color Scripter cs 위 명령들을 하나씩 살펴보면, cargo generate 를 이용해서 기본 템플릿을 이용한 프로젝트 폴더를 생성한다. 만들어진 프로젝트 폴더로 이동 cargo make run  명령을 이용해 빌드 및 실행 cargo generate   를 이용해 프로젝트를 생성했을 때, 기존 템플릿은 make를 이용했기 때문에, gdnative 문서 페이지를 보면  make run   으로 빌드 및 실행 명령어가 안내되어 있지만, 최근 cargo build를 이용하는 방식으로 변경 이 되어서 이제는 cargo make run  을 이용해서 실행해야 빌드 및 실행이 적절하게 동작 한다. 기존에는 비어있는 화면 이었는데, 최근 커밋 에는 기본으로 spinning cube 가 동작하도록 되어 있어서 최신 소스 기반으로 실행을 한다면 아래의 하면을...