OverView
Viven에서의 네트워크 동기화를 수행할 수 있는 방법은 다음과 같습니다.
1.
View를 통한 동기화
2.
RPC를 이용한 동기화
3.
Room프로퍼티를 이용한 동기화
밑에 설명할 View라는 컴포넌트는 VObject의 소유권에 따라 동기화 데이터를 네트워크로부터 받아 해당 컴포넌트에 적용시킬지, 또는 동기화 대상의 데이터를 네트워크로 보낼지를 결정합니다.
이 페이지에서는 이를 활용 할 수 있는 방법을 알아봅니다.
VObject
VObject 컴포넌트는 오브젝트를 서버와 동기화하는 기본 단위입니다.
서로 다른 클라이언트에 존재하는 VObject들은 동일한 NetworkID를 가지고 있습니다. 서버는 NetworkID를 통해 개체를 식별하며, 상태를 동기화하는데 사용합니다.
이를 기반으로 서버는 클라이언트에게 동기화된 데이터를 전송합니다. RPC를 통해 함수를 실행하거나, interactor가 상호작용을 수행하는 등 동기화가 필요한 모든 작업은 VObject를 통해 이루어집니다.
서버에 연결되지 못한 VObject는 상호작용을 수행할 수 없습니다. 다음과 같은 경우 서버와 연결이 끊어집니다.
•
네트워크 오류 등으로 인한 연결 해제
•
만약 중복된 Network ID가 동일한 공간에 존재하는 경우
•
유효하지 않은 Network ID 또는 서버에 등록되지 않은 Network ID가 존재하는 경우
VObject 빌드 시 NetworkID가 잘못 설정되었거나, GameObject.Instantiate 로 VObject를 생성한 경우 오류가 발생할 수 있습니다. 현재 동적으로 VObject를 생성하는 기능은 현재 제공되고 있지 않습니다.
VMap에 포함된 오브젝트는 모두 Prepared 오브젝트이며, 맵 로딩 시 네트워크와 동기화됩니다. VMap 빌드 과정에서 NetworkID의 중복은 확인하지 않습니다. Network ID가 존재한다는 에러가 발생할 수 있습니다.
Viven에서 플레이 중 인 Room 안의 VObject는 각각 소유자가 있으며, 네트워크를 통해 소유자는 변경될 수 있습니다.
여기서 말하는 소유는 네트워크 객체의 소유입니다.
하나의 네트워크 객체의 소유자는 한명으로, 여러명이 될 수 없습니다.
Viven View
View컴포넌트는 Unity 컴포넌트를 네트워크와 동기화하는데 사용합니다.
View컴포넌트는 VObject와 함께 사용하고, 한 VObject에 여러 View컴포넌트를 추가할 수 있습니다.
View컴포넌트는 수행하는 작업들은 다음과 같습니다.
1.
(소유권에 따른) 데이터 동기화
2.
동기화 시의 수행할 작업들
모든 VObject들은 소유권이라는 개념을 가지고 있습니다. 소유권은 네트워크 객체의 동기화를 담당하는 권한을 의미하며, 소유권을 가진 클라이언트를 소유자라고 부릅니다.
각 클라이언트들은 소유권을 가진 VObject의 동기화를 담당합니다. View 컴포넌트는 소유권에 따라 서버에 데이터를 전송하거나, 서버로부터 수신받은 데이터를 컴포넌트에 적용합니다.
소유권은 서버에서 관리되며, 상호작용, 방 입장과 퇴장 등으로 변경될 수 있습니다. 클라이언트는 소유권을 임의로 변경할 수 없으며, 서버와의 요청을 통해 소유권이 변경됩니다.
또한, 서버는 모든 VObject가 언제나 소유자를 가지고 있도록 보장합니다. 방에 아무도 존재하지 않을 경우 VObject는 소유권이 존재하지 않습니다.
예를 들어, TransformView컴포넌트는 해당 GameObject의 Transform데이터를 동기화 합니다.
View 컴포넌트는 소유권에 따라 동기화를 수행합니다.
•
VObject의 IsMine 프로퍼티(VObject의 소유권 여부)가 true이면, Transform 정보를 서버로 송신합니다.
•
VObject의 IsMine 프로퍼티가 true이면, 서버로부터 데이터를 수신해 Transform을 변경합니다.
이를 통하여 내것이 아닌 해당GameObject는 소유자의 Transform을 따라갈 수 있도록 도와줍니다.
Viven에서는 TransformView, RigidbodyView 등 Unity 컴포넌트의 View를 제공하고 있습니다.
VivenCustomSyncView를 사용해 VivenScript에서 CustomView를 작성할 수 있습니다.
RPC
RPC는 Remote Procedure Call(원격 프로시저 호출)의 약자로, 다른 유저의 네트워크 객체 내의 메소드 함수를 원격으로 호출 할 수 있는 기능을 제공합니다. View와 달리 연속적인 데이터 동기화가 아니라, 단방향의 이벤트성 동기화를 위해 사용합니다.
RPC는 VObject를 기반으로 통신합니다. RPC를 송수신 하는 VivenBehaviour는 모두 VivenCustomSyncView 컴포넌트를 가지고 있어야 합니다.
RPC로 실행할 함수는 overload 하지 않아야 합니다.
Lua 함수의 매개 변수 정보를 확인할 수 없어 RPCComponent는 함수 이름을 탐색합니다. 함수 overloading은 의도치 않은 동작을 발생시킬 수 있습니다.
Room 프로퍼티
Room 프로퍼티는 생성된 방 별로 존재하는 테이블입니다. VObject 단위로 동기화되는 View 또는 RPC와 달리 방 단위로 동기화되며 서버에 저장됩니다. Room 프로퍼티의 라이프사이클은 방의 라이프사이클과 동일합니다. 방이 생성되는 순간 정의되며, 방이 삭제될 때 함께 삭제됩니다.
Room 프로퍼티는 플레이어가 맵에 존재하지 않아도 유지됩니다. 따라서 방 내에서 영구적으로 존재해야 하는 데이터를 저장하는데 사용할 수 있습니다. 게임의 리더보드를 저장하거나, 진행상황을 저장해야 할 때 Room 프로퍼티를 활용할 수 있습니다. 반면에 VivenBehaviour의 정보들은 플레이어가 방을 들어올 때 초기화되므로 데이터를 저장할 수 없습니다.
Room 프로퍼티 는 데이터 무결성을 보장하지 않으며, 네트워크 상태에 따라 지연되거나 누락될 수 있습니다. Room 프로퍼티를 바탕으로 동작을 수행할 경우 설정이 완료되었는 지 확인해야 합니다. 또한 여러 클라이언트에서 동일한 Room 프로퍼티를 수정할 경우 데이터가 덮어씌워질 수 있습니다.
Scripting API
Viven Network Object
오브젝트를 동기화하기 위해 사용하는 컴포넌트
displayName
해당 오브젝트의 이름
objectId
오브젝트를 동기화할 때 사용하는 오브젝트의 id. 컴포넌트를 붙이면 자동으로 생성됩니다.
objectSyncType
오브젝트를 동기화하는 방식
•
Continuous : 오브젝트가 매 틱(tick)마다 동기화
•
Manual : 오브젝트가 지정한 타이밍에만 동기화
contentType
오브젝트의 Content Type
RPC
같은 방에 있는 유저들()이 특정한 메소드를 실행할 수 있도록 합니다.
해당 컴포넌트를 사용하려면 VivenNetworkObject 가 있어야 합니다.
RPC로 보내려는 메소드를 overload하지 않도록 주의해 주세요.
SendRPC
같은 방에 존재하는 유저들이 특정 메소드를 실행하도록 할 수 있습니다. RPCSendOption 으로 나를 포함한 모든 유저들 또는 나를 제외한 모든 유저들을 타겟으로 지정합니다.
-- 나를 포함한 모든 방의 유저들에게 보내는 경우
function rpc1()
--
local AllOption = RPCSendOption.All
-- 필요한 parameter는 다음과 같습니다.
-- 1. 실행하도록 하고 싶은 메소드 이름
-- 2. RPC option
-- 3. 실행하려는 메소드의 parameter. 사용 가능한 parameter 개수는 최대 5개입니다.
SyncView:SendRPC("SendAll", AllOption, nil)
end
function SendAll()
-- 이 메소드는 나를 포함한 모든 유저들이 실행하게 됩니다.
end
-- 나를 제외한 모든 방의 유저들에게 보내는 경우
function rpc2()
--
local OthersOption= RPCSendOption.Others
local table = {9, 1}
SyncView:SendRPC("SendOthers", OthersOption, table)
end
function SendOthers(a, b)
-- 이 메소드는 나를 제외한 유저들이 실행하게 됩니다.
-- {9, 1}을 보냈으므로, a = 9, b = 1 입니다.
end
Lua
복사
SendTargetRPC
유저의 id를 입력하여 해당 유저가 특정 메소드를 실행하도록 할 수 있습니다. 유저의 id는 Network:GetRoomUserId 를 사용하여 알 수 있습니다.
function rpc3()
local players = {}
-- 닉네임이 "targetPlayerNickname"인 유저의 id를 받아옵니다.
players[1] = Network:GetRoomUserId("targetPlayerNickname")
SyncView:SendTargetRPC("SendTarget", players, nil)
end
function SendTarget()
-- 닉네임이 "targetPlayerNickname"인 유저만 이 메소드를 실행하게 됩니다.
end
Lua
복사
Viven Rigidbody
해당 오브젝트의 Rigidbody 값을 설정합니다.
originMass
오브젝트의 질량(kg). 기본은 1
originDrag
오브젝트의 항력. 기본은 0 (공기 저항을 받지 않음)
originAngularDrag
오브젝트가 회전할 때 항력. 기본은 0.05
originCom
오브젝트의 질량 중심
Viven Grabbable Rigid View
VivenGrabbableMoudle이 붙어 있는 오브젝트를 동기화하기 위해 사용하는 컴포넌트
Room 프로퍼티
setRoomProp
방의 Property를 설정합니다.
self.setRoomProp("propId", value)
-- 설정하고자 하는 "propId"에 대한 방 property를 요청합니다.
Lua
복사
getRoomProp
방의 Property를 요청합니다.
self.getRoomProp("propId") -- "propId"에 대한 방 property를 요청합니다.
Lua
복사
onGetRoomProp
getRoomProp을 이용하여 요청할 방의 Property를 수신 받을 수 있습니다.
function onGetRoomProp()
--
end
Lua
복사