선 그리기
이 애드온은 DataSyncHelpers 애드온을 사용하여 3D 드로잉을 생성하고 나중에 참여하는 사용자도 이를 받을 수 있는 기능을 시연합니다.
기능
이 애드온은 여러 개의 라인 렌더러로 구성된 3D 드로잉을 생성합니다.
데모 장면에서는 드로잉을 완료한 후 이를 잡고 이동할 수 있습니다.
이 드로잉은 한 사용자만 수정해야 합니다. 여러 사용자가 동시에 수정해야 하는 경우 TextureDrawing 애드온을 참조하십시오. 이 애드온은 이러한 사용 사례를 처리합니다.
이 애드온은 드로잉 도구가 어떻게 사용될지(잡기, 자동 드로잉 등)에 대한 가정을 하지 않으며, 실제 "펜"과 같은 그리기를 위한 간단한 예제도 제공합니다.
원리
드로잉 포인트 동기화
NetworkLineDrawer
라는 드로잉 도구가 NetworkLineDrawing
컴포넌트를 포함한 네트워크 객체를 생성합니다.
이 드로잉 도구는 추가적인 라인과 포인트를 저장하도록 요청하며, 이러한 데이터는 네트워크를 통해 링 버퍼 구조로 공유됩니다. 이 구조는 여러 포인트를 동시에 전달할 수 있도록 하며, Fusion 스트리밍 API를 통해 나중에 참여하는 사용자도 전체 드로잉을 받을 수 있습니다.
손실 없는 링 버퍼 논리에 대한 자세한 내용은 DataSyncHelpers 애드온의 RingBufferLossLessSyncBehaviour 클래스를 참조하십시오.
드로잉 보간
NetworkLineDrawing
은 LineDrawing
객체에 라인 렌더러를 생성하고 이를 채우도록 요청합니다.
NetworkLineDrawing
은 Render
동안 다음과 같은 드로잉 로직을 적용합니다.
상태 권한이 있는 사용자(그리기를 수행 중인 사용자)의 경우, 추가된 드로잉 포인트가 즉시 그려집니다.
원격 사용자의 경우, 두 틱 사이의 포인트 수를 보간하여 표시할 포인트 수를 결정합니다. 이는 NetworkBehaviour
의 TryGetSnapshotsBuffers
메소드를 사용하여 수행됩니다(자세한 내용은 네트워크 버퍼 문서를 참조). 이 메소드는 이전과 현재 데이터를 제공하며, 두 데이터 간의 보간 진행도를 알파 값으로 반환합니다.
C#
if (lastDrawnPoint < (drawingPoints.Count - 1))
{
if (Object.HasStateAuthority || drawPointsOnProxiesAsSoonAsAvailable) {
DrawAllPoints();
}
else
{
bool proxyDrawingAuthorized = lossRanges.Count == 0;
// Find the from and to state of the drawing data (byte array),
// find the entry count in each state (from drawing point count, to drawing point count),
// and interpolate the current max point to draw with the interpolation alpha (between from and to point count)
if (proxyDrawingAuthorized && TryGetSnapshotsBuffers(out var fromBuffer, out var toBuffer, out var alpha))
{
var reader = GetArrayReader<byte>(nameof(Data));
var toData = reader.Read(toBuffer);
var fromData = reader.Read(fromBuffer);
RingBuffer.PositionInfo fromPositionInfo = RingBuffer.PositionInfo.ExtractPositionInfo(fromData);
var fromGlobalByteIndex = fromPositionInfo.totalData - 1;
RingBuffer.PositionInfo toPositionInfo = RingBuffer.PositionInfo.ExtractPositionInfo(toData);
var toGlobalByteIndex = toPositionInfo.totalData - 1;
var fromGlobalIndex = RingBuffer.EntryIndexAtDataSourcePosition<LineDrawingPoint>(fromGlobalByteIndex);
var toGlobalIndex = RingBuffer.EntryIndexAtDataSourcePosition<LineDrawingPoint>(toGlobalByteIndex);
var currentIndex = (int)Mathf.Lerp(fromGlobalIndex, toGlobalIndex, alpha);
DrawPointsUpTo(currentIndex);
}
}
}
완료 핸들러
드로잉이 완료되면, IsFinished
네트워크 변수가 모든 사용자에게 동기화됩니다.
NetworkLineDrawing
은 드로잉이 완료되었을 때 활성화되는 finishedHandler
게임 오브젝트를 가질 수 있습니다.
이 게임 오브젝트에 INetworkLineDrawingListener
를 구현하는 컴포넌트가 있으면, DrawingFinished
콜백을 호출할 수 있으며, 이를 통해 완료된 드로잉의 핸들 위치와 회전을 조정할 수 있습니다.
NetworkLineDrawer API
NetworkLineDrawer
는 자체적으로 아무것도 그리지 않지만, 다른 컴포넌트나 하위 클래스에서 이를 호출해 드로잉을 생성할 수 있습니다.
StartDrawing
: 네트워크 러너를 통해drawingPrefab
프리팹을 생성합니다. 이 프리팹에는NetworkLineDrawing
컴포넌트가 포함되어야 합니다.StopDrawing
: 현재 드로잉을 중지합니다.StartLine(Color color)
: 주어진 색상으로 라인을 시작합니다. 이 라인의 색상은 변경할 수 없습니다.AddPoint([Color color], float pressure)
: 포인트를 추가합니다(새로운 색상으로 변경하면 새로운 라인이 시작됩니다).StopLine()
: 다음에 추가되는 포인트가 새로운 라인으로 시작되도록 강제합니다.
LineDrawingPoint 데이터 구조체
LineDrawingPoint
는 드로잉 포인트의 로컬 위치(드로잉 원점에 상대적)와 압력 수준(해당 위치에서 라인의 너비를 조정)에 대한 정보를 포함합니다.
이 데이터 구조체는 특별한 경우에도 사용됩니다. NEW_LINE_PRESSURE
(즉, -1) 값은 새로운 라인의 시작을 나타내며, 이 경우 Vector3
위치는 시작 라인의 RGB 값을 포함합니다.
종속성
데모
데모 씬은 Assets\Photon\FusionAddons\LineDrawing\Demo\
폴더에서 찾을 수 있습니다.
DemoLineDrawingMeta
데모 씬을 테스트하려면 Meta 패키지를 프로젝트에 설치해야 합니다. 또는 Meta XR 통합 프로젝트를 사용해 이를 직접 테스트할 수 있습니다.
다운로드
이 애드온의 최신 버전은 무료 XR 애드온 프로젝트에 포함되어 있습니다.
지원되는 토폴로지
- 공유 모드
변경 로그
- 버전 2.0.5: DataSyncHelper 2.0.8과의 호환성 추가(ByteArraySize 속성 사용 추가)
- 버전 2.0.4: 3D 드로잉 중 햅틱 피드백 제공 수정
- 버전 2.0.3: NetworkGrabbableLineDrawer의 입력 변경 허용
- 버전 2.0.2: Meta 상호작용 SDK가 설치된 경우에만 MetaGrabbableLineDrawer 지원 추가
- 버전 2.0.1: 드로잉 보간 추가
- 버전 2.0.0: 첫 번째 릴리스