기본 콘텐츠로 건너뛰기

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 코드가 이미 있는 경우, 시작하기 쉽다. 
  • Godot에서 제공하는 도구들과 scene graph를 완전히 이용할 수 있다. 
  • Godot의 실행과 별도로 Rust 기능을 독립적으로 테스트 해 볼 수 있다.
단점
  • 대부분의 게임 로직이 GDScript로 작성되어서 Rust 언어적 특징에서 오는 잇점(타입 안정성과 리펙터링등)을 이용할 수 있다.
  • 게임 로직은 Godot의 scene graph 모델에 맞춰져야 하고 구조적인 변경은 한계가 있다.

Godot scent tree + native scripts

Godot 엔진에서 강제하는 scene tree 구조를 사용하면서 GDScript의 역할을 Rust로 대체 하는 방법.

이런 구조의 경우 장단점은 다음과 같다.

장점
  • Rust로 로직을 작성하지만 Godot의 scene 그래프를 완전히 이용할 수 있다.
  • GDScript의 기존 코드와 개념이 쉽게 계승된다.
단점
  • 구조적 자유도가 Godot의 scene 트리 모델에 의해 제약되어서 적다.
  • godot-rust가 전체 코드에 걸쳐 사용됨에 따라, 게임 로직이 Godot에 밀접하게 엮이게 된다. 테스트 및 기능 분리는 어렵게 되고 Godot과 godot-rust의 버젼 변경에 종속적이게 된다.

Rust game + Godot I/O layer

대부분의 게임은 Rust로 작성되고, 엔진은 input/output 핸들링을 위해서만 사용하는 방법.

전형적인 작업흐름은 다음과 같다.

  • Input: 사용자의 입력과 이벤트(키 눌림, 네트워크 패킷 도착, 타이머, 등)를 수집하기 위해 Godot 엔진을 사용한다.
  • Processing: 수집된 입력은 Rust로 보내진다. 컨트롤러는 게임 시뮬레이션을 진행하고 결과를 만들어 낸다.
  • Output: 이런 결과들은 Godot으로 다시 보내져서 scene에 영향을 준다. (노드의 위치, 에니메이션, 사운드 이펙트 등.)
장점
  • Rust game 로직을 구성하는데 완전히 자유롭다. 자신만의 계층구조를 가질 수 있다.
  • 순수하게 Rust에서 동작하기 때문에, 동작 시뮬레이션을 하는데 Godot이 필요 없게 되서 이런 것 들을 가능하게 해 준다.
    • Rust-only 서버
    • Rust-only unit 및 integration 테스트
    • Different/simplified visualization 백엔드
단점
  • 사전에 Rust 구조를 안전하게 하는 것이 반드시 필요하다.
  • Godot scene 트리와 Rust 구성요소가 같이 동작하는 것을 일일히 조정해야 한다. 이 작업은 대게의 경우 Rust에서 상태의 중복을 위미한다.
이렇게 Rust를 Godot엔진과 사용하는 세가지 방법에 대해 살펴 봤는데, 내 감상은 이렇다. 

첫번째 경우는 이미 GDScript로 작성된 게임이 있는경우 매우 유용한 것 같다. 게임에서 일부 독립적으로 동작하는 부분이 있는 경우, 해당 부분만 Rust로 다시 개발해서 교체 한다면 속도나 안정성면에서 좋은 업그레이드가 될 수 있을 것 같다. 

두번째 방법은 Rust를 사용해 새로 게임을 개발하는 경우 좋은 선택일 듯 하다. 이미 작성된 GDScript가 없는 상태 이므로 굳이 GDScript와 Rust를 번갈아 가면서 개발 하기 보다는, 스크립팅 언어를 한가지로 통일하는 것도 좋을 것 같다. 

세번째 경우는 Godot Engine을 사용하는 의미가 거의 없어 보인다. 게임 엔진을 사용한다는 것은 개발자는 로직에 집중하고 나머지 부분은 엔진에 맡기겠다는 의미인데, 이렇게 하면 이미 게임엔진에서 제공되는 많은 부분을 다시 작성해야 해서 비효율적으로 보인다.

댓글

이 블로그의 인기 게시물

Godot-Rust 개발환경 설정

Godot-Rust 개발환경 설정 우선은 개발환경을 설치해 보면서 하나씩 배워보면 좋을 것 이다. 공식 홈페이지에 Godot 과 Rust 개발환경을 설정하는 방법이 자세히 나와있으니 각각 따라서 잘 설치하면 되지만, Godot과 Rust를 동시에 사용하기 위한 내용을 포함해 다시 정리해 본다. 앞선 게시물에서 Godot에서 C/C++ 바인딩을 위해 GDNative와 헤더를 제공한다고 적었는데, 이를 통해 Rust도 Godot과 바인딩해서 사용할 수 있다. 직접 GDNative와 바인딩 하는 것을 할 수도 있겠지만, 이미 godot-rust 오픈소스 프로젝트에서 안정적으로 바인딩된 상태이므로 이 프로젝트를 사용하면 다시 바인딩 할 필요없이 제공되는 gdnative crate를 사용함으로써 쉽게 Rust를 이용해 Godot 개발을 할 수 있다. Godot Engine Godot 공식 다운로드 페이지 에서 자신의 OS에 해당하는 이미지를 받아서 적절한 폴더(예들들어, ~/Godot/)를 만들고 집어 넣는다. 어느곳 에서도 실행 할 수 있도록, 환경변수에 path를 설정한다. The godot-rust Book  페이지에는 3.2.3-stable을 지원하고 있다고 되어 있는데, 이는 cargo의 dependency에 gdnative crate 버젼을 0.9.3 으로 명시했을때고, 그렇지 않고 github의 주소를 적으면, 3.4.2 (이 글을 작성하는 최신버전) 까지도 문제없이 동작한다. Rust rustup  을 방문하면, rust 에서 공식적으로 제공하는 설치 이미지를 통해 Rust toolcahin을 설치 할 수 있다. (Ubuntu인 경우 curl 을 통해 받아서 설치됨) 설치 후 다음과 같은 명령어를 통해 잘 설치 되었는지 확인할 수 있다. LLVM godot-rust 는 LLVM에 기반한 bindgen을 기반해 바인딩 되어 있기 때문에, LLVM 바이너리를 설치해야 한다. 설치 후 다음 명령을 통해 설치가 잘 되어 있는지 확인 할 수 있다....

Dodge The Creep - [2]

Dodge The Creep - [2] 템플릿 정리하기 Template 정리 본격적으로 tutorial 을 따라하기 전에 우선 프로젝트 설정을 위해 복사해 놓은 template code를 정리할 필요가 있다. 현재 이 template 코드에는 삼차원 큐브가 회전하고 있는 상태이고, rust code의 경우 이 글을 작성하고 있는 현재 시점에서는 에러를 포함하고 있기도 하다. Godot Project Godot 엔진 에디터를 시작해서, 만들어 놓은 프로젝트 폴더의 godot 폴더 안에 있는 project.godot 파일을 열어서 프로젝트를 로딩한다. 왼쪽 하단의 FileSystem 영역을 보면 폴더 구조로 resource들이 나열되어 있는데, res://scenes 아래에 Game.tscn과 SpinningCube.tscn 두개의 scene 파일이 들어 있는 것이 보일 것 이다.  여기서, SpinningCube.tscn은 불필요 하기 때문에 지운다. 그리고나서, Game.tscn 파일을 열어보면 왼쪽 상단 Scene 텝에 scene에 포함된 노드들이 보이는데, 루트노드는 Spatial 타입의 노드이고, 그 밑으로 Camera 와 SpinningCube 노드들이 붙어 있는 것이 보일 것 이다.  우선 Camera와 SpinningCube 노드들워준 후, Game 노드의 타입을 Node2D 타입으로 변경 해 준다. 이제 Godot project 의 정리는 완료 되었다. Rust project 이제 Rust project를 정리해 볼 차례다. 프로젝트 폴더 아래 rust 폴더를 VSCode로 열어보자. 왼쪽 파일 탐색기를 보면, src 폴더아래에 세개의 .rs 파일이 존재 하는 것을 볼 수 있다. 이 중, spinnig_cube.rs를 지우고, lib.rs 안에서 spinning_cube.rs 파일을 호출 하는 부분들을 지워주자. lib.rs 파일을 열면, spinnig_cube 모듈을 로딩 하는 부분과, Godot에 노출하는 클래스로 등록하는 부분...

[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번째 라인에서 버튼을 누르는 동작을 수행 한다.