[7월 19일]
● Event 시스템
- 객체와 객체 간에 주고 받는 형식이며 MOD에서도 이벤트가 많이 사용된다.
- MOD에서 이벤트 시스템을 쉽게 활용할 수 있도록 Entity Event System이라는 API를 기본으로 제공한다.
○ Event : 로직 상에서 사건의 발생을 의미 (Event의 종류의 식별 정보, 추가 정보 소유)
○ Handler : 해당 Event를 받았을 때 처리하는 행동의 주체 : 해당 이벤트가 불렸을 때 불리는 함수 (listener, subscriber 등의 비슷한 용어가 있다.)
○ Sender : 해당 Event를 발송하는 객체 (emitter, dispatcher 등의 비슷한 용어가 있다.)
학급 전체에 공지문을 우편 배달한다고 가정하면, 이때 Event는 공지문이고, Handler는 학급 내 학생들, Sender는 우편 배달원이 되는 것이다.
Event 시스템 | 설명 |
장점 | * 다른 Component나 기능 단위에서 결합성이 떨어짐 * 행위에 대한 액션 추가 희망 시 행위 수행하는 곳 수정 없이 추가 가능 * 다른 Component의 정보를 필요로 하지 않는다. |
단점 | * 사건 발생 시 전체적 플로우 찾기 어렵다. * 각각 처리하는 로직으로 인해 실행되는 시점에서 알 수 없다. * 디버깅이 어려우며, 순차적 행위 수행이 어렵다. |
● LogEvent
- 우리가 이름 붙이는 Event로, Log 간의 이벤트를 집어넣는데 사용될 것이다.
- MyDesk - Create EventType : LogEvent 객체 생성
- LovEvent에 message property 생성
- myComponent 생성 및 Handler와 function 추가
Log로 이벤트를 주고받는 과정 - 쏘는 주체와 받는 주체가 같은 Component인 경우
1. 자신이 엔티티 쪽으로 이벤트를 쏨
2. 로그 이벤트를 받는 핸들러 → 자신의 Entity 쪽으로 등록
● 핸들러 등록 구조
- 각 Entity들은 Component를 포함하고 있으며, Entity Event System은 다음과 같이 동작한다.
- Component는 각 Entity를 중계자로 사용할 수 있음.
- 각 Component는 Entity를 통해 Handler를 등록한다. (Event 발생 역시 Entity를 통해 가능하다.)
- sender 역시 Entity를 통해 이벤트를 발생시키는 것이 가능하며, 이 때 Entity는 Handler들에게 해당 이벤트를 전송하는 역할을 한다.
- 어떤 Event가 왔을 때 이것을 처리하는 부분을 Component 내의 Logic에 넣고, 이벤트 수신 등록을 Register, AddListener 등으로 하며, MOD에서는 Entity에 등록하는 구조이다.
● 이벤트를 주고 받을 때
○ 같은 엔티티에서 이벤트를 주고 받을 때
- component1에서 이벤트 발생 시, component3의 이벤트를 실행시키고 싶을 때를 가정.
- 두 component간에 연관이 없기 때문에 component에서 바로 호출하지 않고 엔티티를 통해 호출하는 구조.
- 1. component1이 특정 타이밍에 의해 Entity로 발송
- 2. Log Event를 수신하겠다고 등록한 Component들에게 Event 발송
- 3. 해당 Component들은 Event를 받아서 처리
○ 다른 엔티티에서 이벤트를 주고 받을 때
- rabbitEntity 쪽으로 이벤트를 쏘면 rabbitComponent가 수신해서 rabbitComponent 안의 로그 메시지가 출력되는 구조
- 1. 신호를 보내는 Entity 쪽에서 Component들이 이벤트 발송
- 2. 받는 Entity 쪽에서 신호를 받고 Event 수행
구현하는 방법에는 두 가지가 있다.
- 첫 번째 방법 : RabbitComponent에서 로그 이벤트 등록 후 MyComponent에서 rabbitEntity 쪽으로 Log Event 발송 등록
- 두 번째 방법 : Rabbitcomponent에서 로그 메시지 핸들 이벤트와 출력 등록(이 때 BeerEntity로 이벤트 발송 등록X) 후, BeerComponent에서 등록한 로그 이벤트를 RabbitEntity로 보내 로그 출력
* 분리되어 있는 환경에서 통신을 할 수 있게 해주는 것을 Event라고 할 수 있겠다.
● 이벤트 처리
- 1. 이벤트를 처리할 컴포넌트 & 엔티티 생성
- 2. 핸들러 로직 추가
- 핸들러 로직이 이루어지는 방법
- 1. Entity Event Handler 추가
- 2. 핸들러 상단 이벤트 중계자 설정
- 3. 이벤트 처리 로직
- 3. 이벤트 발생 로직 추가
이벤트 시스템과 일반 로직의 차이
- "행위가 일어난 주체"에서 일을 처리(로직)할 것인지, "행동을 실행해야 할 주체"에서 일을 처리(이벤트 시스템)할 것인지에 대한 차이입니다.
● Entity
- Entity 생성
- MOD에서는 Entity를 생성할 수 있는 함수인 _SpawnServie를 제공해준다.
- SpawnByEntityTemplate : 배치된 Entity와 동일한 Entity를 생성하는, Entity를 복제해주는 역할을 수행
- 맵 상에 복제 대상이 되는 템플릿 Entity가 반드시 존재해야 한다.
Parameter | Type | Description |
entity | Entity | * 복제할 엔티티를 지정합니다. |
name | string | * 생성할 엔티티의 이름을 설정합니다. |
spawnPosition | Vector3 | * 엔티티가 생성될 위치 좌표를 설정합니다. |
parent(Optional) | Entity | * 생성된 엔티티의 부모가 될 엔티티를 넣어줍니다. |
includeChild(Optional) | boolean | * 복제할 엔티티의 하위 엔티티도 함께 복제할 것인지 설정합니다. |
--void SpawnByEntityTemplate()
--SpawnByEntityTemplate의 파라미터값들을 설정합니다.
local entityTemplate = _EntityService:GetEntityByPath("/maps/map01/object-49_1") -- 맵에 배치한 엔티티를 받아옵니다. 워크스페이스 -> 엔티티 -> 우클릭 -> Copy Entity Path로 패스를 가져올 수 있습니다.
local name = entityTemplate.Name .. "Copy" -- 생성될 엔티티의 이름을 설정합니다.
local spawnPosition = Vector3(0,0,0) -- 생성될 때의 위치 좌표를 설정합니다.
local spawnedEntity = _SpawnService:SpawnByEntityTemplate(entityTemplate, name, spawnPosition) --스폰한 엔티티를 변수로 받으면, 해당 엔티티에 대한 후처리를 할 수 있습니다.
if isvalid(spawnedEntity) == false then log("Spawn Failed") end
- SpawnByModelID : 워크 스페이스에 추가된 모델 중 한 가지 모델을 지정해 엔티티를 생성해 주는 함수
- 모델 리스트에 있는 모델을 Entity로 생성하고자 할 때 사용한다.
Parameter | Type | Description |
id | string | * 워크스페이스에 추가된 모델 중 새로 생성할 엔티티의 템플릿이 될 Model ID를 넣어줍니다. * Model ID는 Workspace - 모델(생성할 엔티티의 템플릿의 되는) - Copy Model ID를 선택해 가져올 수 있습니다. |
name | string | * 생성할 엔티티의 이름을 설정합니다. |
spawnPosition | Vector3 | * 엔티티가 생성될 위치 좌표를 설정합니다. |
parent | Entity | * 생성된 엔티티의 부모가 될 엔티티를 넣어줍니다. |
- 반환 값
- 스폰 성공 시 Entity를 반환합니다.
- 스폰 실패 시 nil을 반환한다.
- 사용 예시
- 개발자 센터 Docs를 참고해보자.
-- void SpawnByModelId()
--SpawnByModelId의 파라미터값들을 설정합니다.
local id = "maplestorymapobject$002be76" -- 워크스페이스 -> Model 하위에 추가된 모델이 있으며, 모델 -> 우클릭 -> Copy Model ID로 ID를 복사해서 가져올 수 있습니다. 앞에 "model://"은 제거해줍니다.
local name = "SpawnedEntity" -- 생성될 엔티티의 이름을 설정합니다.
local spawnPosition = Vector3(0,0,0) -- 생성될 때의 위치 좌표를 설정합니다.
local parent = _EntityService:GetEntityByPath("/maps/map01") -- 생성될 엔티티의 부모 엔티티입니다.
local ownerId = nil -- 엔티티의 소유권을 가질 플레이어의 ID(Name)를 넣어줍니다. 일반적으로 nil로 설정합니다.
local spawnedEntity = _SpawnService:SpawnByModelId(id, name, spawnPosition, parent, ownerId) --스폰한 엔티티를 변수로 받으면, 해당 엔티티에 대한 후처리를 할 수 있습니다.
if isvalid(spawnedEntity) == false then log("Spawn Failed") end
- Entity 삭제
- MOD에서는 Entity를 삭제할 수 있는 함수인 _EntityService:Destroy 또는 Entity:Destroy를 제공해주며, 삭제하고자 하는 엔티티를 위와 같이 지정해 삭제해줄 수 있다.
Parameter | Description |
entity | * 유효성 체크 대상이 되는 엔티티를 넣어줍니다. |
- 반환 값
- 파라미터로 넘겨진 Entity가 존재하는 Entity면 true를, Entity가 nil이거나 삭제 대기 중,
또는 삭제된 Entity라면 false를 반환
--void OnUpdate(number delta) [server only]
if isvalid(self.SpawnedEntity) == false then return end
if self._T.time == nil then self._T.time = 0 end
self._T.time = self._T.time + delta
if self._T.time >= 3 then
_EntityService:Destroy(self.SpawnedEntity)
end
--void OnUpdate(number delta) [server only]
if isvalid(self.SpawnedEntity) == false then return end
if self._T.time == nil then self._T.time = 0 end
self._T.time = self._T.time + delta
if self._T.time >= 3 then
self.SpawnedEntity:Destroy() --_EntityService:Destroy 대신 Entity:Destroy로 교체.
end
- Entity 유효성 체크
- MOD에서는 isValid를 사용해 유효성을 체크한다.
--void OnUpdate(number delta) [server only]
if isvalid(self.SpawnedEntity) == false then return end
if self._T.time == nil then self._T.time = 0 end
self._T.time = self._T.time + delta
if self._T.time >= 3 then
local isvalidValue = isvalid(self.SpawnedEntity)
log("삭제 전 : "..tostring(isvalidValue)) -- 콘솔 창에 "삭제 전: true" 출력
self.SpawnedEntity:Destroy()
isvalidValue = isvalid(self.SpawnedEntity)
log("삭제 후 : "..tostring(isvalidValue)) -- 콘솔 창에 "삭제 후: false" 출력
end
회고 :
*해당 게시글은 Supporters Hackathon 참여자에게 제공되는 MOD 학습 강의와 기본 학습 교안의 내용을 기반으로 작성되었음을 알립니다.
'Coding > 멋쟁이사자처럼' 카테고리의 다른 글
[멋쟁이사자처럼 X 넥슨] MOD Supporters Hackathon 3주차 회고 (10. 컴포넌트의 활용 2) (0) | 2022.07.23 |
---|---|
[멋쟁이사자처럼 X 넥슨] MOD Supporters Hackathon 3주차 회고 (9. 컴포넌트의 활용 1) (0) | 2022.07.23 |
[멋쟁이사자처럼 X 넥슨] MOD Supporters Hackathon 3주차 회고 (7. 네트워크의 이해) (0) | 2022.07.22 |
[멋쟁이사자처럼 X 넥슨] MOD Supporters Hackathon 2주차 회고 (6. 스크립트의 이해) (0) | 2022.07.19 |
[멋쟁이사자처럼 X 넥슨] MOD Supporters Hackathon 2주차 회고 (5. 자주 사용하는 컴포넌트) (0) | 2022.07.14 |