상태
Photon Bolt 핵심에는 상태라고 하는 개념이 있습니다.
Bolt의 State
구현을 사용하여 엔티티
의 네트워크 상태
를 템플릿으로 정의하며(Bolt Assets
윈도우 사용) 여기에는 변환 및 여러 기본 유형에 대한 속성이 포함됩니다.
또한 상태 속성을 IProtocolToken로 구현할 수 있으며 이것은 기본적으로 임의 데이터 유형을 상태 속성으로 구현하는 방법입니다.
각 State
에는 여러 행동을 구성하기 위한 내부 설정들을 가지고 있습니다:
- 상속: 이 설정을 사용하여 상태의 계층을 생성할 수 있습니다. 간단히 말하면 상위
상태
의 모든 속성이 하위 상태에 생성되므로 플레이어 및 적과 같이 상태가 매우 유사한 경우 복제할 필요가 없습니다. - 대역폭: 은 이
상태
가 패킷당 사용할 수 있는 비트 수와 이상태
에서 동시에 패킷에 쓸 수 있는 속성수를 결정합니다. - 임포트 메커니즘 모드:
- 복제 모드: 다른
상태
속성과 마찬가지로 메커니즘 속성의 동기화 방법을 설정합니다. - 메커니즘 모드: 애니메이터 메소드(예:
animator.SetFloat
)를 통해 애니메이터의 속성을 변경하는 방법을 설정하거나Bolt
속성을 대신 사용할지 여부를 설정합니다.
- 복제 모드: 다른
- 임포트 메커니즘 파라미터: 애니메이션 제어에 필요한 모든 파라미터들을 가져오는 기준으로 사용되는
AnimatorController
를 참조합니다. - 압축 초기화 값: 활성화되면
상태
를 기준으로 새 Bolt엔티티
를 생성할 때 초기 변환 위치를 압축하는 방법을 구성할 수 있습니다. 값의 범위를 알고 있고엔티티
를 생성할 때 비트를 저장하려는 경우 이 작업에 도움이 될 수 있습니다.
상태 설명
Bolt 상태
의 장점은 사용자가 네트워크 속성을 자동으로, 변경되는 경우에만 동기화할 수 있다는 것입니다.
게다가, 상태
는 늦에 참여하는 것에 대한 구현을 거의 투명하게 만듭니다.
Bolt 상태
소유주가 속성을 변경할 때마다 Bolt는 해당 엔티티에 현재 범위가 지정된 클라이언트에게 해당 값을 보냅니다.
사용자는 엔티티 동작에 대한 콜백(Attached
에서) 콜백을 구독할 수 있습니다. (여기 참고)
Float
또는 Transform
와 같은 각 State
속성은 기본 값(변경할 수 없는)을 가지고 있으며 엔티티
가 생성될 때 최초로 설정됩니다.
특정 속성 값이 기본값에서 변경되지 않은 경우 Bolt는 이 속성을 어떤 연결에도 동기화하지 않으며 전체 네트워크 전송을 최소화합니다.
상태
는 원시 속성이 충분하지 않은 경우 사용자 지정 속성을 확장할 수 있습니다.
이 작업은 IProtocolToken
구현을 사용하여 수행됩니다. 토큰을 사용하면 사용자 정의 비즈니스 로직을 위한 직렬화를 완벽하게 제어할 수 있습니다.
그러나 토큰 내부의 데이터를 변경해도 Bolt가 변경된 속성을 전송하도록 트리거 하지는 않습니다.
기존 토큰을 다른 토큰으로 변경하거나 null로 설정한 경우(또는 null 토큰을 null이 아닌 토큰으로 변경하는 경우)와 같이 토큰 자체가 변경될 경우에만 Bolt가 토큰을 보냅니다.
토큰은 팩토리에서 생성되므로 Bolt에 등록해야 한다는 점을 기억하십시오.
새 연결이 게임 세션에 참여하면 모든 엔티티가 자동으로 동기화(스코프 기준으로) 됩니다.
변경된 모든 속성도 이 플레이어에게 동기화됩니다.
엔티티/속성의 수에 따라 이 작업 시간은 가변적입니다.
Bolt는 Bolt 설정
에서 설정한 만큼의 초당 패킷만 전송하므로, 결국 모든 데이터가 클라이언트에 도착하게 됩니다.
이렇게 하면 늦게 참여하는 것이 매우 간단해지고 관련된 모든 일반적인 해킹(일반적으로 일종의 메시지 버퍼링)을 방지할 수 있습니다.
상태 복제
볼트는 각 송신 틱(Bolt 설정
에 정의된)에서만 상태 업데이트를 전송합니다. 즉, 속성이 기본적으로 "dirty"로 표시되고 다음 송신 틱까지 평가되지 않습니다.
즉, FixedUpdate
사이에 속성 값을 여러 번 변경하면 볼트 체크 시점의 값만 전송됩니다(즉, 중간 값은 없습니다).
Bolt의 상태
및 그 속성을 다룰 때 명심해야 할 점은 엔티티 소유자만이 그 값을 바꿀 수 있고 네트워크를 통해 복제될 수 있다는 사실입니다.
여기서 유일한 예외는 속성의 복제 모드
(여기 참고)를 컨트롤러를 제외한 모든 사용자
로 설정한 경우입니다. 이 경우 컨트롤러
도 속성 값을 변경할 수 있지만 복제되지 않으며 콜백은 로컬 Controller
에서 발생됩니다.
엔티티가 연결되면 상태 속성이 모두 클라이언트에 도착한다고 보장되지는 않습니다.
일부 데이터가 절대적으로 필요한 경우 이 데이터에 대해 토큰 부착(즉, 토큰을 인스턴스화할 때 IProtocolToken
로 데이터 전송)을 사용하십시오.
토큰을 부착하는 것은 상대적으로 버겁습니다. 토큰은 생성 작업이 승인될 때까지 생성 작업에 대한 각 전송 체크 표시를 전송합니다.
또한 상태 속성은 일반적으로 (Bolt 상태 설정에서 더 높은 우선순위 번호가 더 높은 경우) 우선순위 순서로 수신되지만 특정 순서로 도착한다고 보장되지는 않습니다.
이를 "궁극적인 일관성" 이라고 하며, 상태가 엔티티 소유자와 궁극적으로 일관되게 유지된다는 것입니다.
Bolt가 모든 상태 속성을 패킹할 때 우선순위에 따라 엔티티
를 반복적으로 분류합니다.
Bolt는 각 엔티티에 대해 더티 속성을 정렬하고 패킷 공간이 부족해질 때까지 각 엔티티에 대해 특정 번호(사용자 설정에 정의됨)를 전송(Bolt 패킷 참고)합니다.
이 절차는 연결별로 수행됩니다.
패킷 크기와 Bolt 설정 모두 때문에 상태 속성을 변경한 후 Bolt가 다음 전송 틱에 전송한다는 것은 보장되지 않습니다.
Bolt는 또한 범위
(여기에서 상세 내용 보기)라는 개념이 있으며, 이것은 특정 엔티티
로부터 업데이트를 수신해야 하는 연결을 결정하며 여기에는 속성 변경 사항이 포함됩니다.
기본값은, 모든 연결이 모든 업데이트에서 수신되지만 수동
범위 모드를 사용하여 변경할 수 있습니다.
상태 속성 유형
모든 볼트 상태
는 기본적으로 속성 집합으로 만들어지며, 각 속성 집합은 데이터 형식으로 표시됩니다.
여기서는 엔티티의 상태
를 구축하는 데 사용할 수 있는 모든 속성 유형과 네트워크 레이아웃에 실제 영향을 미칠 수 있는 세부 정보를 설명합니다.
각 속성 유형에는 기본 동작을 조작하는 데 사용되는 자체 구성 집합이 있으며, 압축 옵션을 조정하기 위해 복제 모드
에서 구성될 수 있습니다(모든 필드에 이 설정이 있으며, 여기에서 자세한 내용을 볼 수 있습니다).
일부 에셋 유형에는 메카님
이라는 옵션도 있습니다. 이 속성을 애니메이터
매개 변수로 간주해야 하는지를 제어할 수 있습니다. 이 경우 Bolt가 자동으로 속성 값을 애니메이터 컨트롤러
와 동기화할 수 있습니다(이 페이지 뒷부분에서 설명).
Float:
float
값;- Smoothing 알고리즘:
float
값을 보간하는지에 따라 선택 - 보간 모드: 값을 정규 부동 값 또는 각도로 간주할지 선택합니다. Bolt가 값을 보간할 때
UnityEngine.Mathf.Lerp
또는UnityEngine.Mathf.LerpAngle
을 사용할지 여부를 결정합니다. - 압축: 여기에서 float에 대해 압축 설정을 결정합니다.
- Smoothing 알고리즘:
정수:
정수
값- 압축: 정수 값에 대한 압축 설정
Matrix4x4: 유니티 Matrix4x4 인스턴스
Quaternion: Unity Quaternion 인스턴스
- Smoothing 알고리즘:
Quaternion
값이 보간 되는지의 여부를 선택합니다.UnityEngine.Quaternion.Slerp
를 사용합니다. - Axes:: 축(
X
,Y
,Z
) 이 쿼터니온에 의해 고려해야 하는지 선택합니다. - 엄격한 비교:: 사용으로 설정한 경우,
Quaternion
이 변경되었는지를 판단할 때Quaternion
(q1 != q2
)의 동등 연산자를 사용하는 대신, 각 단일 값은 하나씩 비교(q1.x != q2.x || q1.y != q2.y...
)됩니다. - Quaterinon 압축:
Quaternion
에 있는 각각의 값의 압축 설정을 결정합니다.
- Smoothing 알고리즘:
벡터: Unity Vector3 인스턴스;
- Smoothing 알고리즘:
Vector
값이 보간되어야 하는지의 여부를 결정.UnityEngine.Vector3.Lerp
를 사용합니다. - Axes:: 어떤 축(
X
,Y
,Z
)이 이 벡터에 고려되어야 하는지 선택합니다. - 엄격한 비교:: 사용하는 경우,
Vector
가 변경되었을 때Vector
(v1 != v2
)의 동등 연산자를 사용하는 대신, 하나씩 단일 값을 비교(v1.x != v2.x || v1.y != v2.y...
)합니다. - Teleport Threshold: 값 사이를 보간하지 않고
벡터
값이 제자리에 고정되어야 하는 위치에서 크기 한계를 결정합니다. - Axis 압축:
Vector
상에 있는 각각의 값에 대한 압축 설정을 결정합니다.
- Smoothing 알고리즘:
Bool:
boolean
값String:
string
값- 인코딩 & 길이: 이
문자열
값의 직렬화에 어떤인코딩
을 사용할지와 문자 기준의 최대 길이를 설정할 수 있습니다
- 인코딩 & 길이: 이
Guid:
System.Guid
의 인스턴스색상: Unity Color 인스턴스
Color32: Unity Color32 인스턴스
Entity: 다른
BoltEntity
참조;NetworkId:
Bolt.NetworkId
레퍼런스PrefabId:
Bolt.PrefabId
레퍼런스배열: 동일 형식의 값들의 집합, 배열 형식으로 구성됨.
Floats
또는Strings
의 배열과 유사하게 인덱스를 통해 개별 항목에 접근할 수 있습니다.- Element 유형: 배열의 유형 선택.
- Element 건수: 배열에 저장되어 있는 요소의 건수.
Object:
Object
에셋 유형을 나타냅니다.Object
에셋은 동일한 "상자" 내에 관련 데이터를 저장하는 데 사용할 수 있는 특수 유형의 컨테이너입니다. 또한Bolt Assets
창에 정의되어 있으며 동일한 속성 집합을State
로 정의한 다음 여러 다른State
에서 'Object
정의를 재사용할 수 있으므로 하위 상태로 간주할 수 있습니다.- Object 유형: 여기에서
Object
유형을 선택할 수 있습니다.
- Object 유형: 여기에서
ProtocolToken:
Bolt.IProtocolToken
을 구현하는 사용자 지정 토큰을 참조합니다. 다른 속성 유형에서 정상적으로 전송할 수 없는 임의 데이터를 전송하려는 경우토큰
필드가 유용할 수 있습니다. 이미 언급한 바와 같이,토큰
필드 값을 변경하면 값이 동기화되지 않으며, 토큰 참조(null
또는 새 토큰으로 변경되는 경우에만 해당 값이 업데이트됩니다.Trigger: 트리거는 특별한 하나의 발생 상태입니다. 애니메이션 상태 변경을 트리거 하거나 무기를 발사하기 위해 실행할 수 있는 속성을 원하는 경우 이 경우
트리거
속성이 도움이 될 수 있습니다.Transform: 유니티 트랜스폼 인스턴스.
Transform
속성은 다른 모든 유형과 다릅니다. 선택적 단순 "렌더" 보간뿐만 아니라 보간/외삽도 투명하게 구현됩니다. 최적화로 Bolt는 변환이 이동할 때만 변환 상태를 전송합니다. 객체가 이동하지 않으면 전송되지 않습니다.- Space: 여기서
Transform
이Local
또는World
변환 좌표 공간을 사용하여 변환할지 여부를 정의합니다. 즉,볼트
가localPosition/localRotation
또는position/rotation
을 사용하여GameObject
를 이동할 경우입니다. - Smoothing 알고리즘:
- 없음: 위치와 회전이 새로운 값으로 스냅 됩니다
- 보간: Bolt는
UnityEngine.Vector3.Lerp
과 회전 쿼터니온UnityEngine.Quaternion.Slerp
을 사용하여 위치 백터가 보간합니다. - 추론: Bolt는 현재 속도를 기준으로
Transform
의 위치와 회전을 추정합니다. 이 기능은 방향을 너무 많이 변경하지 않고 네트워크 지연을 보상하려는 개체가 있는 경우 유용합니다.- 추론 가속도: Bolt가 현재 물체의 속도를 계산하거나 가져올 위치를 선택합니다.
- 추론 설정: 여기에서 Bolt가 위치/회전을 추정하는 전방 프레임 수를 구성할 수 있습니다.
- 위치:
Vector
속성 유형과 동일한 설정 - 회전:
Quaternion
속성 유형과 동일한 설정
- Space: 여기서
상태 상호 작용
생성하는 상태
에셋은 특정 엔터티
에 대한 네트워크 레이아웃에 대한 설명일 뿐입니다.
계속하기 전에 예로 사용할 상태
를 설정해야 합니다. SphereState
라는 상태를 사용할 것이며 기본 설정인 4가지 기본 속성을 모두 포함합니다:
Transform
유형의 Transform- 3개 요소를 갖고 있는
Vector
베열
형의 Colors Integer
형식의 CurrentColorTrigger
형식의 Blink
상태 데이터와 상호 작용하고 값을 읽고 쓸 수 있으려면 다음 몇 단계를 수행해야 합니다.
- 새로운 Unity 프리팹을 생성하고 여기에
BoltEntity
컴포넌트를 추가합니다. - State 필드에서
Bolt Assets
창에서 정의한State
를 선택합니다. - 새 C# 스크립트를 생성하여 프리팹에 추가합니다.
- 에셋을 변경한 후에는 Bolt를 다시 컴파일해야 합니다(
Bolt/Compile Assembly
메뉴).
다음에 표시된 그림과 같은 구성이 되어야 합니다:
예제의 SphereController
스크립트를 오픈합니다. Bolt Entity
의 기본 구현은 다음과 유사합니다:
C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereController : Bolt.EntityBehaviour<ISphereState>
{
public override void Attached()
{
// entity initialization
}
}
엔티티
컨트롤러를 만들 때 상태를 관리하는 몇 가지 사항을 기억해야 합니다:
Bolt.EntityBehaviour<YourStateInterface>
또는Bolt.EntityEventListener<YourStateInterface>
에서 확장되어야 합니다. 이 클래스들은UnityEngine.MonoBehaviour
에서 확장되었으므로, 모든 유니티 메소드에 접근할 수 있습니다.- 클래스(
YourStateInterface
)를 정의할 때 제너릭 타입이 전달되며, 접근하려는State
타입을 정의하여GameObject
프리팹에 붙여진BoltEntity
컴포넌트에 설정한 것과 동일해야 합니다. GameObject
와BoltEntity
는 일반적인GameObject
에서 수행된Start
메소드 내부에서Entity
설정을 하는 동안에 이루어지는 서로 다른 초기화 프로세스를 가지고 있습니다. 이 의미는Entity
는 알려져야 되고 초기화되어야 한다는 것입니다. 따라서 일반적으로Start
메소드로 하는 모든 작업은Attached
메소드로 수행해야 합니다.
이제 Entity
를 초기화하고 몇 가지 값을 속성에 연결하는 방법을 자세히 살펴보겠습니다.
C#
public override void Attached()
{
// Link the GameObject with the Bolt Transform Property
state.SetTransforms(state.Transform, transform);
// Init the Colors Array
state.Colors[0] = new Vector3(1, 0, 0);
state.Colors[1] = new Vector3(0, 1, 0);
state.Colors[2] = new Vector3(0, 0, 1);
// Set the Active Color
state.CurrentColor = 0;
}
보시다시피 엔터티와 관련된 State
를 수정하는 것은 포함된 State
변수를 사용하는 것만큼이나 간단하며 각 개별 속성에 접근할 수 있습니다.
이 작업은 상태를 수정하려는 모든 메소드에서 수행할 수 있습니다.
다른 스크립트에서 BoltEntity
에 대한 참조가 있고 상태에 액세스하려면 entity.GetState<YourStateInterface>()
를 호출하십시오.
이 코드에서 중요한 부분 중의 하나는 Bolt가 GameObject의 Transform
과 Transform
의 연결 방법으로 state.SetTransforms
메소드를 사용하여 Bolt는 GameObject
가 움질일 때 자동적으로 위치/회전을 동기화합니다.
위의 코드에 없는 Bolt
와의 다른 관련 통합은 Entity
에 애니메이션이 있고 Bolt
에 모든 매개 변수를 동기화하려는 경우입니다.
이 경우 Animator
참조도 해당 상태에 등록해야 합니다. 이 작업은 단 한 라인으로 수행됩니다.
C#
state.SetAnimator(GetComponentInChildren<Animator>()); // Or wherever your animator is
그런 다음 State
속성이 모두 편집기에서 올바르게 설정된 경우 연결된 속성을 변경하기만 하면 되고 Animator
는 원하는 대로 복제됩니다.
앞에서 언급했듯이 엔터티의 소유자
만 상태를 수정할 수 있으며, 소유자
에서 코드를 실행하려면 if (entity.IsOwner)
로 확인하여 감쌀 수 있습니다.
이 필드는 Entity
를 생성한 피어에서만 true
를 반환합니다.
예를 들어 런타임에 새 값만 할당하면 CurrentColor
를 수정하여 인덱스 0
과 1
사이를 토글 할 수 있으며 관련 메소드를 호출하는 Trigger
속성도 활성화할 수 있습니다(이는 이 속성에서 특히 중요합니다).
이 페이지의 뒷부분에서 이러한 변경 사항에 대응하는 방법에 대해 설명합니다.
C#
private void Update()
{
if (entity.IsOwner == false) { return; }
if (Input.GetKeyDown(KeyCode.C))
{
var current = state.CurrentColor;
current = ++current % 2;
state.CurrentColor = current;
}
if (Input.GetKeyDown(KeyCode.R))
{
var idx = Random.Range(0, state.Colors.Length);
state.Colors[idx] = new Vector3(Random.value, Random.value, Random.value);
}
if (Input.GetKeyDown(KeyCode.F))
{
state.Blink();
}
}
복제 모드
(링크)는 상태 복제 방법 및 누구에게 하는지를 수정하기 때문에 상태 관리 방식에 매우 큰 영향을 줍니다.
기본적으로 모든 속성은 Everyone
모드를 사용하여 생성됩니다. 즉, Only
만 할당할 수 있고 다른 속성은 데이터를 수신하기만 합니다.
그러나 이 값을 Controller를 제외한 모두
로 설정할 수도 있습니다. 즉, 컨트롤러에서 상태 속성 값도 변경할 수 있지만 복제되지는 않습니다.
다음과 같은 경우 Controller를 제외한 모두를 사용하는 것이 좋습니다.
- 컨트롤러에 대한 모든 제어 권한을 허용하려는 속성이 있습니다.
resetState==true
인ExecuteCommand()
에서 서버/소유자로부터 결과 상태로 갱신되는 속성이 있습니다.
반면, Everyone으로 관리해야 하는 경우는:
소유자
가 설정하고 컨트롤러가 설정할 수 없는 속성이 있습니다.
상태 콜백
States
에 값을 쓰는 것의 다른 면은 런타임 시 업데이트에 반응하는 것입니다.
Bolt는 특정 속성 값이 변경되었을 때 자동으로 Bolt
에 의해 호출되는 핸들러인 속성 콜백을 사용하여 이를 수행합니다.
이 기능은 다양한 방식으로 유용하지만, 가장 중요한 것은 상태를 통합할 필요가 없고 필요할 때 새로운 값을 관리하기만 하면 된다는 것입니다.
한 가지 유의할 점은 대부분의 시나리오에서 속성 콜백을 Attached
메소드에 등록한다는 것입니다.
이 이벤트를 받으면 Entity
가 완전히 초기화되고 거기서 상태를 변경할 수 있으며 업데이트도 받을 수 있기 때문입니다.
속성 유형 자체와 관련된 속성 콜백의 세 가지 주요 유형인 simple
, array
, trigger
를 지정할 수 있습니다.
다음 섹션에서는 속성 핸들러를 사용할 수 있도록 각 항목과 코드에 대해 설명합니다.
Simple 콜백
이러한 유형의 콜백은 가장 사용하기 쉽고 가장 많이 사용할 콜백입니다.
특별한 내용은 없으며, 일반 System.Action
과 매우 유사한 위임자 PropertyCallbackSimple
을 따라야 한다는 점입니다:
C#
public delegate void PropertyCallbackSimple();
따라서 이러한 종류의 콜백을 등록하려면 아래 코드를 따르십시오.
C#
public override void Attached()
{
// previous entity setup...
// Callbacks
state.AddCallback("CurrentColor", HandlerCurrentColor);
}
void HandlerCurrentColor()
{
Debug.LogFormat("New current color: {0}", state.CurrentColor);
var currentColor = state.Colors[state.CurrentColor];
var r = (byte) currentColor.x;
var g = (byte) currentColor.y;
var b = (byte) currentColor.z;
GetComponent<Renderer>().material.color = new Color(r, g, b, 1);
}
보시다시피 콜백 등록을 위해 State
자체의 state.AddCallback()
메소드를 사용합니다.
첫 번째 인수는 속성의 이름을 가진 문자열입니다. 철자를 올바르게 입력했는지 확인하고 소문자/대소문자를 주의합니다. 두 번째 인수는 콜백 함수에 대한 레퍼런스일 뿐입니다.
콜백 예제에서 CurrentColor
속성은 Colors
배열에서 올바른 색 인덱스를 얻기 위해 읽습니다.
그런 다음 벡터를 UnityEngine.Color
으로 변환합니다. 색상은 GameObject
의 머터리얼에 할당하여 현재 렌더링 색상을 변경합니다.
객체를 가진 Simple 콜백
State
에서 Object
를 정의했고 각 필드에 대해 콜백을 설정하는 대신 하나의 글로벌 콜백을 원하는 경우 특정 속성에 따라 별도의 메소드를 호출하려면 스위치 문이 아닌 룩-업 테이블을 사용하는 것이 좋습니다.
이것은 필요 이상의 최적화에 가깝고 콜백이 많이 트리거 되고 객체에 많은 필드가 있는 경우에만 도움이 됩니다.
위의 이미지에 표시된 정의를 기반으로 다음과 같은 Actions
룩-업 테이블을 정의할 수 있습니다.
C#
private Dictionary<string, Action> lookupTable;
public override void Attached()
{
// previous entity setup...
// Setup Look-up table
lookupTable = new Dictionary<string, Action>() {
{ "equippedItems.head.ID", () => UpdateSingleArmor(0, state.equippedItems.head) },
{ "equippedItems.body.ID", () => UpdateSingleArmor(1, state.equippedItems.body) },
{ "equippedItems.arms.ID", () => UpdateSingleArmor(2, state.equippedItems.arms) }
};
// Callbacks
state.AddCallback("equippedItems", UpdateNewArmor);
}
private void UpdateNewArmor(IState state, string propertyPath, ArrayIndices arrayIndices)
{
Debug.LogFormat("Updated path {0}", propertyPath);
lookupTable[propertyPath]();
}
private void UpdateSingleArmor(int slot, Item item)
{
Debug.LogFormat("Slot {0} new item {1}", slot, item.ID);
}
이렇게 하면 동일한 콜백을 사용하여 특정 객체
에서 업데이트를 받을 수 있습니다.
배열 콜백
배열
속성을 처리할 때는 마지막 섹션에 나와 있는 것처럼 동일한 단순 콜백을 사용할 수 있지만, 더 많은 인수를 받는 특수 위임자 PropertyCallback
을 사용할 수도 있습니다.
C#
public delegate void PropertyCallback (IState state, string propertyPath, ArrayIndices arrayIndices);
- **Bolt.IState state:**는 메소드내에서
State
타입으로 캐스팅될 수 있습니다(note thatBolt.IState
는 상속된 클래스의 모든 상태입니다).- 이것은 실제의
상태
입니다 (일반적인AddCallback
메서드를 사용하기 위해) 엄격한 타입이 아니며 사용자 자신의 유형에 따라 캐스트 해야 합니다.
- 이것은 실제의
- **string propertyPath:**는 속성의 전체 경로입니다.
- Bolt.ArrayIndices arrayIndices에는 콜백에 붙여지는 배열의 인덱스들을 포함하고 있습니다.
여기서는 이 버전의 콜백 사용 방법에 대한 몇 가지 예를 살펴보겠습니다.
단일 수준 배열
Array
속성에 대한 콜백을 등록하려면 Simple Callback
에서 보았던 것과 매우 유사하지만, 다음과 같이 속성 이름 뒤에 []
를 포함하면 됩니다.
C#
public override void Attached()
{
// previous entity setup...
// Callbacks
state.AddCallback("Colors[]", HandlerColors);
}
void HandlerColors(IState state, string propertyPath, ArrayIndices arrayIndices)
{
var index = arrayIndices[0];
var localState = (ISphereState)state;
var newColor = localState.Colors[index];
Debug.LogFormat("Property {0} with index {1} has changed to {2}", propertyPath, index, newColor);
}
반면, 이 경우 콜백은 조금 더 복잡합니다.
앞에서 설명했듯이, 이제 여러분은 더 많은 아규먼트에 접근할 수 있지만, 정말 간단합니다.
추가적으로 고려해야 할 것은 arrayIndices
아규먼트와 관련이 있습니다.- 실제로 Array
속성에서 변경된 인덱스를 나타내주는 배열입니다.
중첩 배열 콜백
또한 Bolt는 중첩된 Array
속성을 관리할 수 있으며, 매우 강력하지만 신중하게 사용해야 합니다.
이 작업은 Object
속성이 포함된 Object
에셋을 사용하여 수행됩니다. 즉, 이 Object
정의를 배열 속성의 유형으로 사용하는 State
는 중첩된 수준의 배열을 생성합니다.
우리는 코드와 연결하기 위해 다음의 State
와 Object
설명을 예로 들겠습니다.
예제에서는 배열
속성을 가진 객체
가 있으며, 이 정의는 상태
에서 Array
Inventory의 타입으로 사용됩니다.
콜백을 등록하고 예제 Array
에 대한 모든 변경 사항을 처리하려면 콜백 등록을 다음과 같이 확장하여 이 작업을 수행합니다.
C#
public override void Attached()
{
// previous entity setup...
// Callbacks
state.AddCallback("Inventory[].Example[]", HandlerInventory);
}
void HandlerInventory(IState state, string propertyPath, ArrayIndices arrayIndices)
{
var indexInventory = arrayIndices[0];
var indexExample = arrayIndices[1];
var localState = (ISphereState)state;
var newValue = localState.Inventory[indexInventory].Example[indexExample];
Debug.LogFormat("Property {0} with index {1}/{2} has changed to {3}", propertyPath, indexInventory, indexExample, newValue);
}
현재 몇 가지 중첩된 배열인 arrayIndices
가 있으며 더 많은 값으로 채워지며, 각 위치는 중첩된 배열의 해당 수준에서 변경된 인덱스를 나타냅니다.
그래서 arrayIndices
의 인덱스 0
에는 Inventory
의 인덱스 값을 가지고 있고 1
인덱스에는 Example
배열 등과 같이 담겨있습니다. 더 많은 수준의 배열을 가지고 있으면, 예제를 참고해보세요.
트리거 콜백
Trigger
속성은 일반적인 State
속성들과 약간 다르며 state.AddCallback()
을 사용하는 대신 트리거는 이미 C# 위임자입니다.
properties are little difference from the other regular State
properties, instead of using state.AddCallback()
, triggers are already C# delegates. 새 속성 콜백을 등록하기 위해 일반적인 C# 메소드를 사용하여 메서드 옵저버를 등록합니다.
C#
public override void Attached()
{
// previous entity setup...
// Callbacks
state.OnBlink += HandlerBlink;
}
void HandlerBlink()
{
Debug.Log("Blink!");
}
다른 유형의 속성과 가장 큰 차이점은 리스너를 추가할 때 On<TriggerName>
라는 State
속성을 사용한다는 점입니다. 여기서 <TriggerName>
은 트리거 속성의 이름입니다.
자, 예를 들어, Blink
트리거를 만들었고 이것이 우리가 state.OnBlynk
를 콜백에 등록하는 이유입니다.
state.Blink()
는 앞에서 설명한 것처럼 실제로 트리거를 생성/활성화하는 데 사용되는 메소드입니다.