이벤트

목차

이벤트는 네트워크상에서 RPC와 같이 설정하는 Bolt의 방식입니다. 여기서는 Photon Bolt에서 생성할 수 있는 이벤트의 유형, 주요 차이점 및 주요 사용 시나리오에 대해 설명합니다.

Bolt 이벤트 처리 방법과 관련하여 Bolt는 이벤트를 별도의 패킷으로 전송하지 않습니다. Bolt의 작동 방식은 모든 것(상태, 이벤트 등)을 하나의 패킷에 담아 보내는 방식이며, SendRate를 기준으로 단일 패킷에 틱을 보냅니다.

이벤트 유형

글로벌 이벤트

글로벌 이벤트는 Create 또는 Post 메소드에 서로 다른 파라미터를 전달하여 ReliableOrdered 또는 Unreliable 둘 다 될 수 있습니다. 일반적으로 대부분의 글로벌 이벤트는 변경하지 않고 그대로 전달한다면 Reliable 모드이며 기본값입니다.

글로벌 이벤트는 특정 엔티티가 아닌 연결 수준에서 전송됩니다. 즉, 이러한 이벤트를 수신하려면 대상 플레이어를 서버에 연결하기만 하면 됩니다. 이러한 기능은 게임 주변에 존재하는 다음과 같은 용도로 사용됩니다.

  • 인증 처리
  • 플레이어 인벤토리 관리

글로벌 이벤트에는 이벤트를 수신하는 사람을 미세 조정할 수 있는 여러 가지 오버라이드가 있습니다(사용자 인터페이스의 볼트 이벤트에 정의되거나 코드를 통해 재정의됨).

메인 화면으로

엔티티 이벤트

엔티티 이벤트들은 항상 비신뢰이며, 피해 표시 또는 폭발을 보여주기 위한 작은 일회성 효과를 위한 것으로 일시적인 일들이며 한 명의 플레이어가 이 이벤트를 놓쳐도 크게 중요한 사항은 아닙니다.

엔티티 이벤트는 항상 특정 BoltEntity로 전송되며, 이는 BoltEntity 구성 요소에서 가져오거나 이와 유사한 방법으로 대상 엔티티에 대한 참조가 필요하다는 의미입니다.

메인 화면으로

이벤트 신뢰성

신뢰성 있는 이벤트

Bolt에서 신뢰할 수 있는 이벤트는 전송된 순서대로 도착하고 도착하도록 보장됩니다. Bolt로 보낼 수 있는 믿을 만한 사건은 글로벌 이벤트 뿐입니다.

신뢰성 있는 이벤트에는 3 바이트의 오버헤드가 있습니다.

메인 화면으로

신뢰할 수 없는 이벤트

반면에, 신뢰할 수 없는 이벤트들은 Bolt에 의해 다르게 취급됩니다. Bolt는 두 개의 후속 송신 틱으로 이벤트를 패킷에 채우려고 시도합니다. 두 시도 중 하나에 이벤트를 맞출 수 없는 경우 이벤트를 삭제합니다. 기본적으로 Bolt는 남은 공간이 있는 경우 신뢰할 수 없는 이벤트를 패킷 끝에 맞추려고 시도합니다. 이후 두 개의 패킷에서 이벤트를 패킷에 맞추기 위해 시도하고 그 후에는 이벤트를 포기하고 삭제합니다. 이러한 맥락에서 "신뢰할 수 없는" 것은 전통적인 의미의 "신뢰할 수 없는" 네트워크 패킷과는 아무 관련이 없습니다.

신뢰할 수 없는 이벤트의 오버헤드는 1바이트입니다.

메인 화면으로

버퍼링

또한 Bolt는 이벤트를 버퍼링 하지 않습니다. 엔티티 이벤트를 통해 이벤트가 도착하고 엔티티가 존재하지 않는 경우 Bolt는 이벤트를 그냥 삭제합니다. 신뢰할 수 있는 엔티티 이벤트가 필요한 경우 글로벌 이벤트를 이벤트 필드로 엔티티와 함께 사용해야 합니다. 그러나 Bolt가 이벤트와 상태를 단일 패킷으로 함께 포장하므로 모든 것이 각 송신 체크에 대한 패킷으로 만들 수는 없습니다. 즉, 이벤트를 만든 후 바로 엔티티에 보내려고 하면 이벤트가 생성되기 전이나 후에 이벤트가 도착하는 경우가 있다는 것을 알 수 있습니다. Bolt 이벤트와 엔티티는 패킷의 개별 논리적 스트림에 생성되며 서로에 대해 정렬되지 않습니다.

메인 화면으로

Bolt 이벤트 생성

새로운 이벤트 정의를 생성하기 위해서, Bolt Assets 윈도우(Bolt/Assets 메뉴)로 이동하여 우측 마우스 버튼을 클릭하여 New Event를 선택합니다. Bolt Editor 윈도우에서 이벤트 이름을 설정할 수 있으며 누가 이 특정 이벤트를 전송하는 것을 설정하고 이벤트에서 정의될 모든 속성들을 생성하고 설정할 수 있습니다.

한 가지 중요한 관점은 이벤트를 전송하는 주체를 허용하는 것입니다. Global Events에 대해서는 다음 사항을 선택할 수 있습니다. (i) Everyone은 서버와 클라이언트 피어가 이 이벤트를 전역적으로 송신할 수 있습니다. (ii) Only Server는 서버만이 이러한 이벤트를 생성할 수 있습니다. (iii) Only Clients는 서버가 아닌 클라이언트가 전송할 수 있습니다. (iv) None은 이 아무도 이벤트를 전역적으로 보낼 수 없습니다. Entity Events에서 선택할 수 있는 옵션은 다음과 같습니다. (i) Everyone는 누구라고 이 이벤트를 전송하는 것이 허용됩니다. (ii) Only Owner는 엔티티를 생성한 피어만이 이 이벤트를 전송할 수 있습니다. (iii) Only Controller는 엔티티 컨트롤러가 이 엔티티로부터 이벤트를 전송할 수 있습니다. (iv) None은 엔티티 이벤트로서 이 이벤트를 아무도 전송할 수 없습니다.

Event Definition
Event Definition.

이벤트를 정의한 후, Bolt를 컴파일(Bolt/Compile Assembly 메뉴)해야 할 필요가 있습니다. 현시점에서, Bolt는 이벤트를 위해 Bolt Event 클래스에서 상속된 새로운 클래스를 생성할 것입니다. 따라서, EventTest라는 이벤트를 생성했다면, Bolt가 생성해 줄 것입니다(이 이벤트 메타데이터는 Visual Studio에서 우측 클릭 후 Go To Definition를 클릭하여 볼 수 있습니다).

public class EventTest : Event
{
    // ...
}

그런 다음 정적 생성 방법 중 하나를 사용하여 이벤트를 만들 수 있습니다. 이러한 각 방법을 사용하여 엔드 포인트 정보를 지정할 수 있습니다. 대상 정보를 지정하지 않으면 볼트에 지정된 이벤트의 기본값이 사용됩니다. 특정 연결에만 이벤트를 보내려면 해당 이벤트에 대한 재정의가 있어야 합니다.

// For Global Events
public static EventTest Create();
public static EventTest Create(ReliabilityModes reliability);
public static EventTest Create(GlobalTargets targets);
public static EventTest Create(GlobalTargets targets, ReliabilityModes reliability);
public static EventTest Create(BoltConnection connection);
public static EventTest Create(BoltConnection connection, ReliabilityModes reliability);

// For Entity Events
public static EventTest Create(BoltEntity entity);
public static EventTest Create(BoltEntity entity, EntityTargets targets);

이벤트를 생성한 후에는 이벤트를 데이터로 채울 수 있습니다. Bolt 코드 생성기는 Bolt 및 컴파일된 Bolt에서 이벤트를 생성할 때 추가한 모든 데이터에 대한 필드를 생성합니다. 예를 들어, 만일 우리가 이 행사를 위해 볼트에 integerMyField라고 불리는 필드를, MyTextString으로 추가했다면, 우리는 다음과 같이 할 수 있습니다.

void SendEvent()
{
    // Create and setup
    var myEvent = EventTest.Create(GlobalTargets.AllClients);
    myEvent.MyField = 5;
    myEvent.MyText = "hello event!";

    // Send the event
    myEvent.Send()
}

Create API를 확장한 볼트는 위에서 설명한 생성 메소드와 동일한 서명을 가지면서도 이벤트 전 분야에 대한 매개 변수를 포함하는 Post(Bolt 버전 1.2.13부터 사용 가능)라는 이름으로 생성합니다. 또한 Post 메소드는 호출 시 이벤트를 자동으로 전송합니다. 따라서 이전 코드는 다음과 같이 다시 쓸 수 있습니다.

void SendEvent()
{
    // Create, setup and send
    EventTest.Post(GlobalTargets.AllClients, 5, "hello event!");
}

두 메소드를 아무 문제 없이 모두 사용할 수 있습니다.

메인 화면으로

글로벌 이벤트 수신하기

Bolt.GlobalEventListener로 부터 상속을 받고 씬에 추가하여 글로벌 이벤트를 수신할 수 있습니다. Bolt는 자동으로 모든 GlobalEventListeners를 찾아 Bolt가 시작할 때 씬에 있으면 등록합니다. 그러나 Bolt는 종료 후 등록을 취소할 예정이므로 싱글톤 수신기를 사용하고 리스너가 계속 청취하도록 하려면 상속된 클래스에서 PersistBetweenStartupAndShutdown을 오버라이드하고 true를 반환해야 합니다.

GlobalEventListener 상속 클래스를 [BoltGlobalBehaviour()]로 구성할 수 있으며, 다양한 파라미터를 사용하여 Bolt가 시작될 때 자동으로 해당 Listener가 생성되도록 할 수도 있습니다(이 속성을 사용하는 두 가지 일반적인 시나리오가 네트워크 유형별 수신자(예: 클라이언트 대 서버) 또는 씬별 수신자 추가). 이 사항은 튜토리얼에서 사용됩니다.

GlobalEventListener에서 상속된 클래스가 있으면, 이벤트를 수신 받아 로직을 구현하는 것에 관심이 있으면 Global Event를 위한 이벤트 핸들러를 간단하게 오버라이드 할 수 있습니다.

BoltNetwork.AddGlobalEventListener 그리고 BoltNetwork.RemoveGlobalEventListener를 가진 리스너를 등록할 수도 있습니다. GlobalEventListener 를 잊고 이 인터페이스들을 구현하여 리스너를 수동으로 등록할 수도 있습니다.

이벤트에 설정한 속성 외에도, Bolt에는 다음과 같은 몇 가지 다른 필드도 포함되어 있습니다.

  • evt.FromSelf: 자신의 연결에서부터 전송된 이벤트인 경우에 true를 리턴
  • evt.IsGlobalEvent: 글로벌 이벤트인 경우 true, 엔티티 이벤트인 경우 false를 리턴
  • evt.RaisedBy: 이 이벤트에 의해서 발생된 연결
  • evt.BinaryData:: 이벤트 데이터의 원시 바이트

이러한 속성들에 대해서는 API 문서 여기를 참고하세요.

메인 화면으로

IEventListener

이 인터페이스는 MonoBehaviour/GameObject이 미사용(기본값으로 발생되지 않습니다)으로 되어있는 상태에서 여전히 발생되는 이벤트를 수정하기 위해 Bolt.GlobalEventListener, Bolt.EntityEventListener 그리고 Bolt.EntityEventListener<T>에서 구현될 수 있습니다.

public interface IEventListener
{
    bool InvokeIfDisabled { get; }
    bool InvokeIfGameObjectIsInactive { get; }
}

예제:

[BoltGlobalBehaviour(BoltNetworkModes.Server)]
public class BoltServerCallbacks : Bolt.GlobalEventListener, Bolt.IEventListener
{
    public bool InvokeIfDisabled { return true; }
    public bool InvokeIfGameObjectIsInactive { return true; }

    // event callback overrides below
}


기술문서 TOP으로 돌아가기