본문 바로가기

레퍼런스/고도엔진

고도엔진 튜토리얼 #10 자원, 리소스(Resources)

노드와 리소스


지금까지, 노드는 엔진의 행동과 특징을 고도의 가장 중요한 데이터 타입인 노드를 통해서 암시했습니다. 고도에는 그 만큼 중요한 데이터 타입이 하나 더 있는데요. 바로 자원(Resource)입니다.


노드는 스프라이트를 그리고, 3D 모델을 그리며 물리, GUI 컨트롤 등의 행동에 집중합니다.


자원은 단순히 데이터 저장소입니다. 이것은 그들이 어떠한 행동이나 정보의 프로세스를 수행하지 않는다는 뜻입니다. 자원은 그저 데이터를 담고 있을 뿐입니다.


자원의 예로는 Texture, Script, Mesh, Animation, Sample, AudioStream, Font, Translation 등이 있습니다.


고도에서 씬(.scn 또는 .xml), 이미지(.png, .jpg), 스크립트(.gd)나 많은 것들을 저장한 파일들을 저장하거나 로드할때 그것들은 자원으로 간주됩니다.


자원이 디스크에서 로드될 때, 항상 한 번만 로드됩니다. 이것은 만약 복사본이 메모리에 이미 로드되어 있다면, 그 자원을 로드하려고 할 때 그 같은 메모리의 복사본을 반복해서 리턴해줍니다. 자원에 대한 진실은 그냥 이 자원이 데이터 컨테이너라는 사실입니다. 그러니까 굳이 복사할 필요가 없습니다.


통상적으로, 고도의 모든 오브젝트(노드, 리소스 또는 다른 것들)는 속성(export)을 출력할 수 있습니다. 자원은 많은 타입(string, integer, Vector2 등..처럼요)이 될 수 있는데, 그 중 하나가 자원이 될 수도 있습니다. 이것은 노드와 리소스 모두 속성으로서의 리소스를 포함할 수 있다는 것입니다. 좀 더 시각화해서 보죠 :


../../_images/nodes_resources.png



외장 vs 내장(built-in)


자원 속성은 자원을 두 방향으로 참조할 수 있습니다. 외장 혹은 내장으로요.


좀더 자세히 보기 위해, 스프라이트텍스쳐가 있습니다 :


../../_images/spriteprop.png

미리보기의 오른쪽에 ">" 버튼을 눌러서 확인하고 자원 속성을 편집할 수 있습니다. 속성 중 하나인 (path)는 이 파일이 어디서 왔는 지 보여줍니다. 이 경우에는 png 이미지에서 왔음을 알 수 있습니다.


../../_images/resourcerobi.png

자원이 파일에서 왔을 때, 여러분은 파일이 외장되어 있는 자원이라는 걸 알 수 있습니다. 만약 path 속성이 지워져 있거나, 애초부터 path가 없다면 내장 자원으로 간주될 수 있습니다.


예를 들자면, 위의 예에서 "path" 속성의 '"res://robi.png"'가 지워지고 씬을 저장할 때 이 자원은 .scn 씬 파일의 안에 저장되며 더 이상 외장된 "robi.png"를 참조하는 것이 아니게 됩니다! 그러나 내장으로 저장되어 있더라도 씬이 여러 번 인스턴스화 될 수 있습니다. 그럴 때에도 자원은 딱 한 번 로드됩니다. Robi robot 씬이 같은 때에 여러 번 인스턴스화 되어도 같은 이미지를 공유하게 되는 겁니다.



코드에서 리소스를 로딩하기


코드에서 리소스를 로딩하는 것은 쉽습니다. 두 가지 방법으로 할 수 있습니다. 첫번째 방법은 load()를 쓰는 겁니다. 이렇게요 :


func _ready():
        var res = load("res://robi.png") # resource is loaded when line is executed
        get_node("sprite").set_texture(res)


두번째 방법은 좀 더 최적화 된 방법입니다. 하지만 오직 문자열 상수 매개 변수(string constant parameter) 상태에서만 작동합니다. 왜냐하면 이건 컴파일 시간에 자원을 로드하기 때문입니다.


func _ready():
        var res = preload("res://robi.png") # resource is loaded at compile time
        get_node("sprite").set_texture(res)



씬을 로딩하기


씬도 역시 자원이지만, 함정이 있습니다. 씬은 디스크에 PackedScene 형태로 저장됩니다. 이는 씬이 자원 안에 포장된다는 것을 뜻합니다.


씬의 인스턴스를 얻기 위해서 PackedSecne.instance() 메소드가 반드시 사용되어야 합니다.


func _on_shoot():
        var bullet = preload("res://bullet.scn").instance()
        add_child(bullet)


이 메소드는 노드를 계층에서 생성합니다. 어떤 다른 노드에도 추가 될 수 있게 모든 속성의 집합을 구성하고 씬의 루트 노드를 반환합니다.


이 접근은 몇가지 이점이 있습니다. PackedScene.instance() 기능이 매우 빠르기 때문에, 씬에 추가 컨텐츠를 효율적으로 추가할 수 있습니다. 새로운 적, 총알, 이펙트 등이 디스크에서 매번 접근하지 않고도 쉽고 빠르게 추가되거나 제거할 수 있습니다. 이미지, 메시 등 언제나 씬 인스턴스 사이에 공유된다는 것을 중요하는 게 중요합니다.



자원 반환


자원은 참조에서 확장된 것입니다. 따라서 자원이 더 이상 사용되지 않을 때는 자동으로 사용 가능한 자원이 됩니다. 대부분의 경우 자원이 노드, 스크립트 또는 다른 자원에 포함되어 있기 때문에 노드를 제거하거나 반환하면 하위 자원도 모두 반환됩니다.



스크립팅


고도에 있는 다른 오브젝트 처럼, 노드뿐만 아니라, 자원들도 스크립트로 작성될 수 있다. 그러나 일반적으로 자원이 데이터 컨테이너이기 때문에 큰 이점은 없습니다.