PUN Classic (also called PUN1) is the original and first major version of PUN. It is now replaced by PUN2 which is refactored and enhanced. We highly recommend starting new projects with PUN2 and if possible migrating existing ones from PUN1 to PUN2 by following our "Migration Notes". PUN Classic will be maintained for the coming months. We will fix important bugs and support new Unity versions but new features will be added only to PUN2.

WebGL 백그라운드 탭

사용자들이 복수 브라우저 탭을 오픈 했을때는, 활성(보이는)탭 만이 고속으로 정기적으로 업데이트 됩니다. 비활성(보이지 않는)탭들은 대부분의 브라우저에서 1초에 한번 업데이트 될 뿐 입니다. 이 경우에 있어서 윈도우가 앞에 있는 가시성은 중요하지 않으며 또한 다른 윈도우에 의해 가려지거나 포커스가 없을 수도 있습니다.

이것은 Unity의 WebGL 익스포트에도 적용되며 수신 및 발신 메시지가 1초에 한 번만 처리되므로 문제가 발생 할 수 있습니다. 이 의미는 메시지 큐가 커지게되고 저속으로 업데이트가 되기 때문에 처리를 위해 더 많은 업데이트가 필요하다는 것입니다. 많은 앱들은 탭이 백그라운드에서 작동하는 동안 점점 더 많은 동기화가 이루어지지 않고 연결이 끊어집니다.

WebGL 어플리케이션은 JavaScript를 사용하기 때문에 브라우저에서 메시지를 게임 로직으로 직접 보내기 위해 이러한 빌드들을 확장 할 수 있습니다. 여기에는 게임에서 연결을 끊거나 어플리케이션 탭이 백그라운에 있을 때 낮은 업데이트 속도 사이에 추가 업데이트를 적용 할 수 있는 가능성을 포함하고 있습니다. 이렇게 하기 위해서는 다음의 접근법 중 하나를 따라 할 수 있습니다.

WebGL 빌드 변경

접근법에 대해서 이야기하기 전에 어플리케이션 탭이 백그라운드에 있는지를 결정하는 방법에 대해 먼저 살펴보도록 하겠습니다. 따라서 우리는visibilitychange 이벤트를 후킹하여 변경 사항을 리슨합니다. 다른 두 상태가 있습니다: hidden 과 "any other state". 상태 변화를 감지 할 때 마다 게임 로직에서 게임 객체에 메시지를 보내고 이런 방식으로 함수를 실행할 수 있습니다. 다음 JavaScript 코드 스니펫을 사용하여 보여 줄 수 있습니다.

<script>

document.addEventListener('visibilitychange', function () {
    if (document.visibilityState == "hidden") {
        SendMessage("Receiver", "DoSomething");
    } else {
        SendMessage("Receiver", "DoSomethingElse");
    }
});

</script>

위의 경우에서 'Receiver' 라고 하는 게임 오브젝트에 메시지를 전송하고 있습니다. 이 객체에서는 DoSomething(Else) 라고 하는 함수를 실행하고 있습니다. 이 함수는 게임 객체에 붙여진 어떤 스크립트 내부에서도 위치 시킬 수 있습니다.

WebGL 어플리케이션에서 이 코드를 붙이기 위해서는 빌드를 탐색하여 생성된 index.html 파일을 오픈하세요. 위의 스니펫을 복사하여 붙일 수 있고 html 파일의 34 라인 <body> 태그 내부에 삽입합니다. 'SendMessage' 함수의 매개변수들을 조정하는 것을 잊지 마세요.

Back To Top

첫 번째 방법 - 연결 해제

첫 번째 방법은 WebGL 어플리케이션 탭이 백그라운드로 들어가면 클라이언트를 Photon에서 연결 해제하는 것 입니다. 이것은 어플리케이션이 포어그라운드로 다시 될 때, Photon으로 (재)연결을 시도할 것 입니다. 설명된 시나리오를 처리하기 위해 권장되는 방식입니다.

이렇게 하기 위해서는 index.html 파일에서 위에 나온 코드 스니펫을 사용하여 게임 로직에서 'Disconnect'및 'Reconnect' 함수로 메시지를 전송합니다. 이러한 함수는 다음의 예제와 같이 보일 것 입니다:

public void Disconnect()
{
    PhotonNetwork.Disconnect();
}

public void Reconnect()
{
    if (!PhotonNetwork.connected && wasConnected)
    {
        PhotonNetwork.ReconnectAndRejoin();
    }
    else
    {
        PhotonNetwork.ConnectUsingSettings("1.0");
    }
}

참고: 부울 변수wasConnected는 클라이언트가 이전에 방에 들어 왔을 때 true로 설정됩니다. 이 정보를 가지고 있음으로써 먼서 로비에 참여하는 대신 룸에 다시연결하고 재참여를 직접 시도할 수 있습니다.

ReconnectAndRejoin를 올바르게 사용하기 위해서는 룸과 룸의 옵션들을 올바르게 설정해야 합니다. 이 의미는 PlayerTtl(플레이어가 서버에서 제거되기 전에 연결 해제 후 얼마나 오랫동안 비활성화 될 수 있는지를 나타냅니다. 단위 밀리초)를 0보다 큰 값으로 설정해야 한다는 의미입니다. 빈 룸을 유지하기 원하는 경우에는 EmptyRoomTtl(서버에서 룸이 제거될 때 까지 얼마나 오랫동안 비어있는 룸을 유지할 것인지, 단위 밀리초)를 0보다 큰 값으로 설정해야 합니다. 이 방법을 사용하여 ReconnectAndRejoin 을 테스트 할 때는 두 값 모두 30,000 (30 초) 또는 심지어 60,000(60 초)로 설정하는 것이 좋을 것 입니다.

Back To Top

두 번째 방법 - 관심 그룹을 사용하고 연결을 살아있는 상태로 유지하기

두 번째 방법은 게임 로직 및 특히 네트워킹 로직에 대한 추가 작업이 필요합니다. 이 접근 방식을 사용하는 것은 게임 관련 메시지를 보내거나 받지 않고 연결을 계속 유지하는 것 입니다. 특정 그룹으로 부터의 빠른 구독 또는 구독해제를 하기 위해 관심 그룹을 사용하여 달성하는 것 입니다.

PUN이 사용하는 기본 그룹은 0입니다. 이 그룹에서는 구독해제를 할 수 없기 때문에, 이것을 사용하여 문제를 해결 할 수는 없습니다.

위에서 설명한 것처럼 이 방식을 사용할 때 다른 관심 그룹이 필요합니다. 다음의 예제에서 그룹 1을 사용하여 이 그룹에서 자유롭게 구독 및 구독해제 하도록 하였습니다.

Photon에 연결할 때 원하는 그룹에서 송신과 수신이 가능한지 확인하세요. 다음을 호출하여 이를 수행할 수 있습니다:

PhotonNetwork.SetReceivingEnabled(1, true);
PhotonNetwork.SetSendingEnabled(1, true);

또한 인스턴스화된 게임 개체 (PhotonView 컴포넌트가 연결된 개체)가 그룹 변수를 원하는 그룹으로 설정했는지 확인하세요. 예를들어:

public void Awake()
{
    GetComponent<PhotonView>().group = 1;
}

대부분의 네트워크 트래픽을 특정 그룹으로 '이동한' 경우 브라우저의 JavaScript에서 호출되는 이 두 가지 함수를 계속 추가 할 수 있습니다. 예제에서는 'Subscribe' 와 'Unsubscribe' 로 이름을 부여했습니다. 두 함수는 다음과 같습니다:

public void Subscribe()
{
    GetComponent<PhotonView>().group = 1;

    PhotonNetwork.SetReceivingEnabled(1, true);
    PhotonNetwork.SetSendingEnabled(1, true);
}

public void Unsubscribe()
{
    GetComponent<PhotonView>().group = 2;
    PhotonNetwork.SetReceivingEnabled(1, false);
    PhotonNetwork.SetSendingEnabled(1, false);
}

마지막 단계에서 할 일은 앞서 설명한 두 가지 함수를 호출 할 수 있도록 "index.html" 파일에 추가 할 JavaScript 스니펫을 조정하는 것입니다.

이것은 많은 문제를 일으킬 수 있고 실제로 해결할 수 있는 것보다 많은 문제를 야기 할 수 있기 때문에 이 문제를 해결하기 위한 권장되는 방법은 아닙니다.

Back To Top

세 번째 방법 - 강제 업데이트와 연결 상태 유지

이 방법은 모든 수신 및 발신 메시지의 처리를 강제로 하기 때문에 이전의 두 방식과는 다릅니다. 따라서 기본 자바 스크립트 스니펫을 다음과 같이 조정해야 할 필요가 있습니다:

<script>

var isActive;

document.addEventListener('visibilitychange', function () {
if (document.visibilityState == "hidden") {
    isActive = setInterval(function() { SendMessage("Receiver", "DoSomething"); }, 250);
} else {
    clearInterval(isActive);
    isActive = false;
}
});

</script>

이것은 현재 보이는 상태를 기반으로 타이머를 생성하고 파괴합니다. 이 타이머가 활성화되면 각 함수는 250 ms 또는 1초에 4회 호출됩니다. SendMessage 함수의 매개 변수뿐만 아니라 요건에 맞게 간격을 조정할 수 있습니다.

이 업데이트가 있으므로 WebGL 프로젝트도 계속 조정할 수 있습니다. 그러므로 우리는 앞서 소개 한 타이머에서 호출 될 DoSomething 함수를 생성합니다. 이 함수는 다음과 같습니다:

public void DoSomething()
{
    if (!PhotonNetwork.connected || !PhotonNetwork.inRoom)
    {
        return;
    }

    PhotonNetwork.networkingPeer.DispatchIncomingCommands();
    PhotonNetwork.networkingPeer.SendOutgoingCommands();
}

브라우저의 탭이 백그라운드에 있어도 네트워크의 메시지 흐름이 증가합니다. 이것이 좋은 아이디어 인것 같지만 이 방식 역시 큰 단점을 가지고 있습니다. 게임이 실제로 보이지 않을 때 캐릭터를 제어 할 수 없기 때문에 캐릭터의 변형과 관련된 사항은 변경되지 않습니다. 따라서 항상 동일한 정보를 다른 클라이언트에게 보냅니다. 이 의미는 중요한 콘텐츠가 없는 메시지 수가 증가 한다는 것 입니다. 그래서 이 모든 접근법은 모두 권장되지 않습니다.

Back To Top

네 번째 방법 - 세 번째 방법을 조정하여 계속 연결 유지

세 번째 방법을 권장하지 않을지라도 가장 마지막 방식에서 사용할 수 있습니다. 따라서 'DoSomething' 함수를 다음과 같이 변경 합니다:

public void DoSomething()
{
    PhotonNetwork.networkingPeer.SendAcksOnly();
}

이 연결을 유지하기 위해 단순히 서버에 인지를 보냅니다. 추가로 생성 된 간격에 관련된 게임 로직은 처리되지 않습니다.

To Document Top