/// <summary> /// Reads a network message and updates local state data using interpolation /// </summary> /// <param name="message">Received payload</param> /// <param name="lerpVal">interpolation value</param> public void LerpRead(BinaryReader message, float lerpVal) { short id = message.ReadInt16(); TransformBroadcasterChangeType changeType = (TransformBroadcasterChangeType)message.ReadByte(); if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Name) || TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Layer) || TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Parent) || TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.IsActive)) { return; } GameObject mirror = StateSynchronizationSceneManager.Instance.FindGameObjectWithId(id); if (mirror == null) { return; } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Position)) { mirror.transform.localPosition = Vector3.Lerp(mirror.transform.localPosition, message.ReadVector3(), lerpVal); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Rotation)) { mirror.transform.localRotation = Quaternion.Slerp(mirror.transform.localRotation, message.ReadQuaternion(), lerpVal); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Scale)) { mirror.transform.localScale = Vector3.Lerp(mirror.transform.localScale, message.ReadVector3(), lerpVal); } }
private void OnConnected(SocketEndpoint endpoint) { if (TransformBroadcaster != null) { Destroy(TransformBroadcaster); } TransformBroadcaster = this.gameObject.EnsureComponent <TransformBroadcaster>(); }
private void OnConnected(INetworkConnection connection) { if (TransformBroadcaster != null) { Destroy(TransformBroadcaster); } TransformBroadcaster = this.gameObject.EnsureComponent <TransformBroadcaster>(); }
/// <summary> /// Writes child transforms hierarchy to network message /// </summary> /// <param name="message"></param> public void WriteChildHierarchyTree(BinaryWriter message) { int childCount = CachedTransform.childCount; message.Write(childCount); for (int i = 0; i < childCount; i++) { TransformBroadcaster childTransform = CachedTransform.GetChild(i).GetComponent <TransformBroadcaster>(); message.Write(childTransform.Id); message.Write(childTransform.CachedName); childTransform.WriteChildHierarchyTree(message); } }
protected override void WriteRenderer(BinaryWriter message, byte changeType) { if (HasFlag(changeType, SkinnedMeshRendererChangeType.Mesh)) { message.Write(NetworkAssetId); } base.WriteRenderer(message, changeType); if (HasFlag(changeType, SkinnedMeshRendererChangeType.Bones)) { Transform[] bones = Renderer.bones; int numBones = bones.Length; message.Write((UInt16)numBones); for (int i = 0; i < numBones; i++) { TransformBroadcaster rootBoneTransform = bones[i].GetComponent <TransformBroadcaster>(); message.Write(rootBoneTransform.Id); } } }
/// <inheritdoc /> protected virtual bool ShouldSendChanges(INetworkConnection connection) { return(TransformBroadcaster.ShouldSendTransformInHierarchy(connection)); }
/// <inheritdoc /> protected virtual void Awake() { transformBroadcaster = GetComponent <TransformBroadcaster>(); StateSynchronizationSceneManager.Instance.AddComponentBroadcaster(this); }
/// <inheritdoc /> public void OnFrameCompleted(NetworkConnectionDelta connectionDelta) { if (!isUpdatedThisFrame) { isUpdatedThisFrame = true; if (TransformBroadcaster != null && (isActiveAndEnabled || UpdateWhenDisabled)) { // Make sure the transform syncs before any other components sync if (TransformBroadcaster != this) { TransformBroadcaster.OnFrameCompleted(connectionDelta); } BeginUpdatingFrame(connectionDelta); // The TransformBroadcaster might detect that this component is destroyed. // If so, don't continue updating. if (this.enabled) { EnsureComponentInitialized(); IReadOnlyList <INetworkConnection> connectionsNeedingCompleteChanges; IReadOnlyList <INetworkConnection> filteredEndpointsNeedingDeltaChanges; IReadOnlyList <INetworkConnection> filteredEndpointsNeedingCompleteChanges; using (StateSynchronizationPerformanceMonitor.Instance.MeasureEventDuration(PerformanceComponentName, "ProcessConnectionDelta")) { TransformBroadcaster.ProcessConnectionDelta(connectionDelta, out connectionsNeedingCompleteChanges, out filteredEndpointsNeedingDeltaChanges, out filteredEndpointsNeedingCompleteChanges); } if (connectionsNeedingCompleteChanges != null && connectionsNeedingCompleteChanges.Count > 0) { SendComponentCreation(connectionsNeedingCompleteChanges); } if (filteredEndpointsNeedingDeltaChanges != null && filteredEndpointsNeedingDeltaChanges.Count > 0) { TChangeFlags changeFlags = CalculateDeltaChanges(); if (HasChanges(changeFlags)) { SendDeltaChanges(filteredEndpointsNeedingDeltaChanges, changeFlags); } } if (filteredEndpointsNeedingCompleteChanges != null && filteredEndpointsNeedingCompleteChanges.Count > 0) { SendCompleteChanges(filteredEndpointsNeedingCompleteChanges); } if (connectionDelta.RemovedConnections != null && connectionDelta.RemovedConnections.Count > 0) { RemoveDisconnectedEndpoints(connectionDelta.RemovedConnections); } EndUpdatingFrame(); } } } }
/// <inheritdoc /> protected virtual bool ShouldSendChanges(SocketEndpoint endpoint) { return(TransformBroadcaster.ShouldSendTransformInHierarchy(endpoint)); }
/// <inheritdoc /> public void OnFrameCompleted(SocketEndpointConnectionDelta connectionDelta) { if (!isUpdatedThisFrame) { isUpdatedThisFrame = true; if (TransformBroadcaster != null && (isActiveAndEnabled || UpdateWhenDisabled)) { // Make sure the transform syncs before any other components sync if (TransformBroadcaster != this) { TransformBroadcaster.OnFrameCompleted(connectionDelta); } BeginUpdatingFrame(connectionDelta); // The TransformBroadcaster might detect that this component is destroyed. // If so, don't continue updating. if (this.enabled) { EnsureComponentInitialized(); endpointsNeedingCompleteChanges.Clear(); endpointsNeedingDeltaChanges.Clear(); filteredEndpointsNeedingCompleteChanges.Clear(); filteredEndpointsNeedingDeltaChanges.Clear(); filteredEndpointsNotNeedingDeltaChanges.Clear(); foreach (SocketEndpoint endpoint in connectionDelta.AddedConnections) { endpointsNeedingCompleteChanges.Add(endpoint); if (ShouldSendChanges(endpoint)) { filteredEndpointsNeedingCompleteChanges.Add(endpoint); } } foreach (SocketEndpoint endpoint in connectionDelta.ContinuedConnections) { if (fullyInitializedEndpoints.Contains(endpoint)) { endpointsNeedingDeltaChanges.Add(endpoint); if (ShouldSendChanges(endpoint)) { filteredEndpointsNeedingDeltaChanges.Add(endpoint); } else { filteredEndpointsNotNeedingDeltaChanges.Add(endpoint); } } else { endpointsNeedingCompleteChanges.Add(endpoint); if (ShouldSendChanges(endpoint)) { filteredEndpointsNeedingCompleteChanges.Add(endpoint); } } } SendComponentCreation(endpointsNeedingCompleteChanges); TChangeFlags changeFlags = CalculateDeltaChanges(); if (HasChanges(changeFlags) && filteredEndpointsNeedingDeltaChanges.Any()) { SendDeltaChanges(filteredEndpointsNeedingDeltaChanges, changeFlags); } if (filteredEndpointsNeedingCompleteChanges.Count > 0) { SendCompleteChanges(filteredEndpointsNeedingCompleteChanges); foreach (SocketEndpoint endpoint in filteredEndpointsNeedingCompleteChanges) { fullyInitializedEndpoints.Add(endpoint); } } foreach (SocketEndpoint endpoint in endpointsNeedingDeltaChanges) { if (!ShouldSendChanges(endpoint)) { fullyInitializedEndpoints.Remove(endpoint); } } UpdateRemovedConnections(connectionDelta); EndUpdatingFrame(); } } } }
/// <summary> /// Reads a network message and updates local state data /// </summary> /// <param name="sendingEndpoint">Sender endpoint</param> /// <param name="message">Received payload</param> public override void Read(SocketEndpoint sendingEndpoint, BinaryReader message) { short id = message.ReadInt16(); TransformBroadcasterChangeType changeType = (TransformBroadcasterChangeType)message.ReadByte(); GameObject mirror = null; RectTransform rectTransform = null; if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.RectTransform)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); rectTransform = mirror.GetComponent <RectTransform>(); if (rectTransform == null) { rectTransform = mirror.AddComponent <RectTransform>(); } } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Name)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.name = message.ReadString(); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Layer)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.layer = message.ReadInt32(); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Parent)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); short parentId = message.ReadInt16(); int siblingIndex = message.ReadInt32(); Transform newParent; if (parentId == TransformBroadcaster.NullTransformId) { newParent = StateSynchronizationSceneManager.Instance.RootTransform; } else { newParent = StateSynchronizationSceneManager.Instance.GetOrCreateMirror(parentId).transform; } if (siblingIndex < newParent.childCount) { Transform existingChildAtIndex = newParent.GetChild(siblingIndex); if (existingChildAtIndex.gameObject.name == temporaryGameObjectName) { Destroy(existingChildAtIndex.gameObject); } } else { for (int i = newParent.childCount; i < siblingIndex; i++) { GameObject temp = new GameObject(temporaryGameObjectName); temp.SetActive(false); temp.transform.SetParent(newParent); temp.transform.SetSiblingIndex(i); } } mirror.transform.SetParent(newParent, worldPositionStays: false); mirror.transform.SetSiblingIndex(siblingIndex); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Position)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.transform.localPosition = message.ReadVector3(); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Rotation)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.transform.localRotation = message.ReadQuaternion(); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.Scale)) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.transform.localScale = message.ReadVector3(); } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.IsActive)) { bool isActive = message.ReadBoolean(); if (isActive) { mirror = mirror ?? StateSynchronizationSceneManager.Instance.GetOrCreateMirror(id); mirror.SetActive(true); } else { mirror = StateSynchronizationSceneManager.Instance.FindGameObjectWithId(id); if (mirror != null) { mirror.SetActive(false); } } } if (TransformBroadcaster.HasFlag(changeType, TransformBroadcasterChangeType.RectTransform)) { RectTransformBroadcaster.Read(rectTransform, message); ComponentExtensions.EnsureComponent <RectTransformObserver>(mirror).CaptureRectTransform(); } }