2020. 6. 17. 01:12ㆍDEFOLD/메뉴얼
실행 중인 게임을 제어하는 코드는 플레이어가 보고 듣는 것과 이동, 확장, 애니메이션, 삭제 및 조작하기 위해 모든 개체와 구성 요소에 접근할 수 있어야 합니다. 델포드의 주소 지정 메커니즘이 이것을 가능하게 한다.
Identifiers (식별자)
Defold는 Game Object와 Component를 참조하기 위해 주소(또는 URL)를 사용합니다. 이러한 주소는 식별자로 구성됩니다. 다음은 Defold가 주소를 사용하는 방법의 모든 예입니다.
local id = factory.create("#enemy_factory")
label.set_text("my_gameobject#my_label", "Hello World!")
local pos = go.get_position("my_gameobject")
go.set_position(pos, "/level/stuff/other_gameobject")
msg.post("#", "hello_there")
local id = go.get_id(".")
아주 간단한 예로 시작해 보죠. 스프라이트 구성 요소가 하나인 게임 개체가 있다고 가정합니다. 게임 오브젝트를 제어하는 스크립트 구성 요소도 있습니다. 편집기의 설정은 다음과 같습니다.
이제 게임이 시작될 때 스프라이트를 비활성화하여 나중에 스프라이트가 나타나게 할 수 있습니다. 이 작업은 다음 코드를 "컨트롤러. 스크립트"에 넣으면 쉽게 수행됩니다.
function init(self)
msg.post("#body", "disable")
end
예상대로 작동할 것이다. 게임이 시작되면, 스크립트 컴포넌트는 식별자 "body"으로 스프라이트 컴포넌트에 주소를 지정하고 이 주소를 사용하여 스프라이트에 "disable" 메시지를 보냅니다. 이 특별한 엔진 메시지의 효과는 스프라이트 컴포넌트가 스프라이트 그래픽을 숨겨라라는 메세지 입니다. 과학적으로 설정은 다음과 같습니다.
임의로 여기서는 게임 오브잭트에게 식별자 "bean"을, 스프라이트 컴포넌트의 이름을 "body"으로, 캐릭터를 제어하는 스크립트 컴포넌트의 이름을 "controller"로 설정 했습니다.
만약 이름을 설정하지 않으면 편집기가 선택합니다. 편집기에서 새 게임 오브젝트 또는 컴포넌트를 생성할 때마다 고유 ID속성이 자동으로 설정됩니다.
게임 오브젝트는 자동으로 열거자와 함께"go"라는 ID를 얻습니다 ("go2" , "go3"등).
컴포넌트는 컴포넌트 유형에 해당하는 ID를 얻습니다 ("sprite" , "sprite2"등).
원하는 경우 자동으로 할당된 이러한 이름을 사용할 수 있지만 식별자를 이해하기 쉬운 좋은 이름으로 변경하는 것이 좋습니다.
이제 다른 스프라이트 컴포넌트를 추가하여 bean에 shield를 줍니다.
새 컴포넌트는 게임 오브젝트 내에서 고유하게 식별되어야 합니다. 이름을 "body"으로 지정하면 스크립트 코드가 "disable"메시지를 보낼 스프라이트에 대해 모호하게 됩니다. 따라서 고유한(그리고 설명적인) 식별자 "shield"를 선택합니다. 이제 우리는 원하는 대로"body"과 "sheild"스프라이트를 활성화하거나 비활성화할 수 있습니다.
동일한 식별자를 두번 이상 사용하려고 하면 편집기에서 오류 신호가 표시되므로 실제로는 문제가 되지 않습니다.
이제 게임 오브젝트를 더 추가하면 어떻게 되는지 살펴보겠습니다. 두개의 "bean"을 작은팀으로 짝을 마추기로 가정해 보자. 여러분은 이 게임 오브젝트들 중 하나를 "bean"이라고 부르고 다른 하나를 "buddy"라고 부르기로 결정합니다. 게다가, "bean"이 한동안 놀고 있을 때,"buddy"에게 춤을 추기 시작하라고 말해야 한다. 이는 "bean"에 있는 "controller"스크립트 구성 요소에서 "partner"에 있는 "controller"스크립트로 "dance"라는 사용자 지정 메시지를 전송하여 이루어집니다
"controller"라는 이름의 두개의 개별 컴포넌트가 있는데, 각 게임 개체가 새로운 naming context를 생성하기 때문에 이는 완전히 합법적입니다.
메시지의 수신인이 게임 오브젝트에서 메시지를 보내는 외부에 있으므로("bean"), 코드는 메시지를 수신할 "controller"를 지정해야 합니다. 대상 게임 오브젝트 ID와 컴포넌트 ID를 모두 지정해야 합니다. 컴포넌트에 대한 전체 주소는 다음과 같습니다. "buddy#controller"그리고 이 주소는 두개의 분리된 부분으로 구성되어 있다.
- 첫번째 먼저 목표 게임 오브젝트의 ID("buddy")가 옵니다.
- 그런 다음 게임 오브젝트/컴포넌트 구분 문자("#")를 따릅니다.
- 마지막으로 대상 컴포넌트의 ID("controller")를 작성합니다.
예전 예제를 보면 게임 오브젝트 식별자를 생략하면 코드가 현재 게임 오브젝트의 구성 요소를 가르키는것을 알 수 있습니다. 예를 들어,"#body"는 현재 게임 오브젝트의 컴포넌트 "body"에 대한 주소를 나타냅니다. 이 코드는 "body"구성 요소가 있는 한 모든 게임 오브젝트에서 작동하므로 매우 유용합니다.
Collection
Collection을 통해 게임 오브젝트의 그룹 또는 계층을 만들고 제어된 방식으로 재사용할 수 있습니다. 게임을 콘텐츠로 채울 때는 Collection 파일을 편집기에서 템플릿(또는"prototype" 또는 "prefabs")으로 사용합니다.
많은 수의 bean/buddy팀을 만들려고 한다고 가정합니다. 이 작업을 수행하는 좋은 방법은 새 Collection 파일에 템플릿을 생성하는 것입니다("team.collection"으로 이름 지정). Collection 파일에 팀 게임 오브젝트를 빌드하고 저장합니다. 그런 다음 해당 컬렉션 파일의 컨텐츠 인스턴스를 기본 부트 스트랩 컬렉션에 추가하고 인스턴스에 식별자를 지정합니다(이름:"tem_1").
이 구조로 "bean"게임 오브젝트는 여전히 주소로 "buddy"에 있는 "controller"구성 요소를 참조할 수 있습니다. ("buddy#controller")
그리고"team.collection"의 두번째 인스턴스(이름:"team_2")를 추가하면 "tema_2"스크립트 구성 요소 내에서 실행되는 코드도 똑같이 작동합니다. 집합"team_2"의 "bean"게임 오브젝트 인스턴스는 여전히 주소에 의해"buddy"의 "controller"구성 요소를 주소로 지정할 수 있습니다. ("buddy#controller").
Relative addressing(상대 주소 지정)
"buddy#controller"는 상대 주소이기 때문에 두 컬렉션의 게임 오브젝트에 대해 작동합니다. 각 컬렉션 "team_1" 및 "team_2"는 새로운 naming context를 생성하거나 원하는 경우 "namespace"를 생성합니다. Defold는 collection이 다음을 해결하기 위해 만든 naming context를 고려하여 naming collisions(충돌)을 방지합니다.
"team_1" naming context내에서 게임 오브젝트 "bean"과 "buddy"는 고유하게 식별됩니다.
마찬가지로, naming context인 "team_2"에서 게임 오브젝트 "bean"과 "buddy"도 고유하게 식별됩니다.
상대 주소 지정은 대상 주소를 확인할 때 현재 naming context를 자동으로 미리 지정하여 작동합니다. 코드를 사용하여 게임 개체 그룹을 만들고 게임 전반에 걸쳐 효율적으로 재사용할 수 있기 때문에 이 기능은 매우 유용하고 강력합니다.
Defold는 두가지 유용한 상대 주소 단축을 제공합니다.
"."
현재 게임 오브젝트를 선택
#
현재 컴포넌트를 선택
예를 들면 다음과 같다.
-- 이 게임 오브젝트가 입력 포커스를 얻도록 해라
msg.post(".", "acquire_input_focus")
-- 현재 스크립트에 재설정 하도록 한다.
msg.post("#", "reset")
Game object paths
naming 메커니즘을 올바르게 이해하기 위해 프로젝트를 만들고 실행할 때 어떤 일이 발생하는지 살펴보겠습니다.
1. editor는 부트 스트랩 컬렉션("main.collection")과 모든 컨텐츠(게임 개체 및 기타 컬렉션)를 읽습니다.
2. 각각의 정적인 게임 오브젝트에 대해 컴파일러가 식별자를 만든다. 이러한 개체는 부트 스트랩 루트에서 시작하여 Collection 계층에서 개체까지 "path"로 구성됩니다. '/' 문자가 각 수준에 추가됩니다.
위의 예를 들어, 게임은 다음과 같은 4개의 게임 오브젝트로 실행됩니다.
- /team_1/bean
- /team_1/buddy
- /team_2/bean
- /team_2b/buddy
식별자는 해시 되며 식별자는 해시된 값으로 저장됩니다. 런타임시 상대 문자열을 absolute id로 계속 해시 하는데 사용되는 각각의 collection ID의 해시 상태도 저장합니다.
런타임에 collection 그룹이 없습니다. 컴파일 전에 특정 게임 오브젝트가 어떤 컬렉션에 속했는지 알 수 있는 방법이 없습니다. 또한 collection에 있는 모든 객체를 한번에 조작하는 것도 가능하지 않습니다. 이러한 작업을 수행해야 하는 경우 코드를 사용하여 쉽게 추적할 수 있습니다. 각 개체의 식별자는 정적이므로 개체의 수명 동안 고정된 상태를 유지할 수 있습니다. 즉, 개체의 ID를 안전하게 저장하고 나중에 사용할 수 있습니다.
Absolute addressing (절대 주소 지정)
주소 지정 시 위에서 설명한 전체 식별자를 사용할 수 있습니다. 대부분의 경우 컨텐츠 재사용이 가능하기 때문에 상대적 주소 지정이 선호되지만 절대적으로 주소 지정이 필요한 경우도 있습니다.
예를 들어 각 bean 개체의 상태를 추적하는 AI관리자를 원한다고 가정합니다. 당신은 bean이 그들의 활동적인 지위에 보고하기를 원하고, 매니저는 그들의 지위에 따라 전략적인 결정을 내리고 bean들에게 명령을 내린다. 이 경우 스크립트 컴포넌트가 포함된 단일 관리자 게임 오브젝트를 생성하여 팀 컬렉션과 함께 부트 스트랩 컬렉션에 배치하는 것이 완벽합니다.
그리고 나서 bean은 관리자에게 상태 메시지를 보낼 책임이 있으며, 적을 발견하면 접촉하고, 부딪치면 아프다!라는 메세지를 manager에 보내기 위해 bean컨트롤러 스크립트는 절대 주소 지정을 사용하여 "manager"의 "controller" 구성 요소에 메시지를 보냅니다.
'/' 로 시작하는 모든 주소는 게임 세계의 루트에서 해결됩니다. 이는 게임 시작 시 로드되는 부트 스트랩 컬렉션의 루트에 해당합니다.
manager 스크립트의 절대 주소는 다음과 같습니다."/manager#controller"이 절대 주소는 어디에서 사용되든 올바른 구성 요소로 결정됩니다.
Hashed identifiers(해시 식별자)
엔진은 모든 식별자를 해시된 값으로 저장합니다. Component 또는 게임 오브젝트를 인수하는 모든 함수는 문자열, 해시 또는 URL개체를 허용합니다. 우리는 위의 주소를 지정하기 위해 문자열을 사용하는 방법을 보아 왔다.
게임 오브젝트 식별자를 얻으면 엔진은 해시된 절대 경로 식별자를 항상 반환합니다.
local my_id = go.get_id()
print(my_id) --> hash: [/path/to/the/object]
local spawned_id = factory.create("#some_factory")
print(spawned_id) --> hash: [/instance42]
문자열 ID 대신 이러한 식별자를 사용하거나 직접 구성할 수 있습니다. 해시된 ID는 개체에 대한 경로(즉, 절대 주소)에 해당합니다.
상대 주소가 문자열로 지정되어야 하는 이유는 엔진이 지정된 문자열이 해시에 추가된 상태에서 현재 명명 컨텍스트(collection)의 해시 상태를 기반으로 새 해시 ID를 계산하기 때문입니다.
local spawned_id = factory.create("#some_factory")
local pos = vmath.vector3(100, 100, 0)
go.set_position(pos, spawned_id)
local other_id = hash("/path/to/the/object")
go.set_position(pos, other_id)
-- This will not work! Relative addresses must be given as strings.
local relative_id = hash("my_object")
go.set_position(pos, relative_id)
URLS
사진을 완성하려면 Defold 주소의 전체 형식인 URL을 살펴보겠습니다. URL은 개체이며 일반적으로 특수 형식의 문자열로 작성됩니다. 일반 URL은 세 부분으로 구성됩니다.
[socket:][path][#fragment]
Socket(소켓)
대상의 게임 월드를 식별합니다. 이는 수집 프록시로 작업할 때 중요하며 동적으로 로드되는 수집을 식별하는 데 사용됩니다.
path(경로)
URL의 이 부분은 대상 게임 오브젝트의 전체 ID를 포함합니다.
fragment(조각)
지정된 게임 오브젝트 내에서 컴포넌트 요소의 ID입니다.
위에서 본 바와 같이, 여러분은 대부분의 경우에 이 정보의 일부 또는 대부분을 생략할 수 있습니다. 소켓은 거의 지정할 필요가 없으며, 항상 지정하는 것은 아니지만 종종 경로를 지정해야 합니다. 다른 게임 세계에서 문제를 해결해야 하는 경우 URL의 소켓 부분을 지정해야 합니다. 예를 들어, 위의 "manager" 게임 오브젝트에 있는 "controller" 스크립트의 전체 URL문자열은 다음과 같습니다.
"main:/manager#controller"
team_2의 버디 컨트롤러는 다음과 같습니다.
"main:/team_2/buddy#controller"
다음과 같은 메시지를 보낼 수 있습니다.
-- manager 스크립트 및 팀 buddy의 controll에 "hello"를 보냅니다.
msg.post("main:/manager#controller", "hello_manager")
msg.post("main:/team_2/buddy#controller", "hello_buddy")
Constructing URL objects
URL개체는 Lua코드로 프로그래밍 방식으로 구성할 수도 있습니다.
-- 문자열에서 URL 객체를 생성:
local my_url = msg.url("main:/manager#controller")
print(my_url) --> url: [main:/manager#controller]
print(my_url.socket) --> 786443 (internal numeric value)
print(my_url.path) --> hash: [/manager]
print(my_url.fragment) --> hash: [controller]
-- 파라메터을 통해 URL 구성:
local my_url = msg.url("main", "/manager", "controller")
print(my_url) --> url: [main:/manager#controller]
-- 비어있는 URL 객체로 빌드:
local my_url = msg.url()
my_url.socket = "main" -- specify by valid name
my_url.path = hash("/manager") -- specify as string or hash
my_url.fragment = "controller" -- specify as string or hash
-- my_url에 지정된 대상에 hello_manager 메세지 전송
msg.post(my_url, "hello_manager!")
'DEFOLD > 메뉴얼' 카테고리의 다른 글
7. Importing assets (0) | 2020.06.17 |
---|---|
6. Application lifecycle (0) | 2020.06.17 |
4. Building blocks (0) | 2020.06.16 |
3. 라이브러리 (0) | 2020.06.16 |
1. 용어사전 (0) | 2020.06.16 |