-
Photon 동기화 방식 - RPC Method게임 클라이언트 개발/Photon 2023. 11. 5. 05:05
#️⃣ 들어가며
Unity에서 Photon PUN을 사용할 때, 여러 플레이어 간의 데이터를 동기화하기 위해 자주 사용하는 기능이 RPC(Remote Procedure Call)이다. 이번 글에선 RPC의 개념부터 Photon에서의 RPC 사용법, 주의사항에 대해 정리했다.
1️⃣ RPC란?
별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게하는 프로세스 간 통신 기술
(출처 : 위키백과)RPC(Remote Procedure Call)는 네트워크를 통해 별도의 원격 제어 없이 다른 클라이언트에서 특정 함수를 실행하는 방식이다. 예를 들어, A 유저가 공격 버튼을 눌렀을 때, B와 C 유저의 화면에서도 그 공격 이펙트를 보여줘야 할 때 RPC를 사용한다.
2️⃣ RPC 사용법
✅ RPC 메서드 선언
[PunRPC] private void InstantiateAttackEffectRPC(Vector3 position) { // position의 위치에 공격 이펙트를 생성하는 로직 }
- [PunRPC] 어트리뷰트를 부여해야 호출 가능
- 네이밍 컨벤션으로는 마지막에 RPC를 붙인다. (다른 컨벤션이 있다면 해당 컨벤션 사용)
- 함수의 파라미터는 int, float, string 등 기본 타입만 사용할 수 있다.
byte, boolean, short, int, long, float, double, string, byte-array, int-array, <type> 배열, hashtable, dictionary, Vector2, Vector3, Quaternion, PhotonPlayer
✅ RPC 메서드 호출
RPC 메서드는 Photon View Component의 맴버 함수 RPC를 통해서만 호출할 수 있다. 또한 다른 오브젝트의 Photon View Component를 통해서도 호출할 수 있다. RPC 함수는 총 두 가지 버전으로 오버로딩 되어있으며 그 프로토 타입은 다음과 같다.
public void RPC(string methodName, RpcTarget target, params object[] parameters); public void RPC(string methodName, Player targetPlayer, params object[] parameters);
파라미터 설명 methodName 호출하고자 하는 함수의 이름 target / targetPlayer 함수를 호출하고자 하는 타겟 플레이어 parameters 호출하고자 하는 함수에 필요한 매개변수 리스트 photonView.RPC(nameof(InstantiateAttackEffectRPC), RpcTarget.AllViaServer, new Vector3(0, 0, 0));
✅ RpcTarget 종류와 차이
RpcTarget 값 설명 All 모든 클라이언트에 함수 호출. (자기 자신 포함)
단, 로컬 클라이언트에서 먼저 실행 후 다른 클라이언트에 전달하기에 호출 시점이 달라질 수 있다.AllBuffered All과 같으나, 버퍼에 함수를 저장하여 이후 접속한 클라이언트에게도 저장된 모든 함수들이 호출됨. AllViaServer 서버를 통해 모든 클라이언트에 함수 호출. 로컬 클라이언트와 다른 사람들의 함수 실행 타이밍이 같다는 장점이 있으나, 네트워크 연결 상태에 따라 지연이 발생할 수 있음. AllBufferedViaServer AllViaServer + Buffered MasterClient 방장(MasterClient)에서만 호출 Others 로컬 클라이언트를 제외한 모든 클라이언트에서 호출 OthersBuffered Others + Buffered
3️⃣ 주의사항 및 팁
📌 Buffered 사용 시 메모리 누수 주의
RpcTarget 중 Buffered 키워드가 붙은 Target을 사용할 경우 해당 함수를 버퍼에 모두 저장했다가 새로운 플레이어가 방에 입장할 때 모두 실행되며, 이로 인한 네트워크 과부화가 발생할 수 있다. 이를 방지하기 위해 PhotonNetwork.RemoveRPCs 또는 PhotonNetwork.RemoveBufferedRPCs를 통해 버퍼를 정리할 필요가 있다.
public static void RemoveRPCs(Player targetPlayer); public static bool RemoveBufferedRPCs(int viewId = 0, string methodName = null, int[] callersActorNumbers = null);
📌 협업 시 nameof() 사용 권장
RPC 메서드의 파라미터인 methodName은 "InstantiateAttackEffectRPC"와 같이 문자열로도 메서드의 이름을 넘길 수 있다. 다만, 오타 발생 시 디버깅이 어려워지므로 nameof()을 활용하여 안정성을 확보하는 것이 중요하다.
// 오타 발생 시 디버깅이 어려워짐 // photonView.RPC("InstantiateAttackEffectRPC", RpcTarget.AllViaServer, new Vector3(0, 0, 0)); photonView.RPC(nameof(InstantiateAttackEffectRPC), RpcTarget.AllViaServer, new Vector3(0, 0, 0));
📌 PhotonServerSettings Scriptable Object
RPC 메서드를 선언하면 PhotonServerSetting Scriptable Object에 해당 RPC 메서드의 이름이 저장된다. 프로젝트를 혼자 진행할 경우 큰 문제가 발생하지 않는다. 하지만 여러 명에서 프로젝트를 진행할 경우 Git 등 협업 툴을 이용해서 버전을 관리하는데, 보통은 스크립트만 Git에 올려놓는다. 즉, 스크립트 이외의 파일들(Scriptable Object와 같은 여러 리소스들)은 동기화가 되지 않기 때문에 해당 에셋에 RPC 메서드의 이름이 저장되있지 않다면 에러를 발생시킨다. 기본적으로 생성되는 경로는 다음과 같으니 협업 시 반드시 확인하길 바란다.
Assets > Photon > PhotonUnityNetworking > Resources > PhotonServerSettings
Photon을 사용하면 생성되는 Scriptable Object 에셋 '게임 클라이언트 개발 > Photon' 카테고리의 다른 글
Photon을 활용한 Matching 시스템 구축 (0) 2024.01.16 Photon 동기화 방식 - Custom Properties (0) 2023.11.07 Photon 동기화 방식 - Photon View Component (0) 2023.11.03