/// <summary> /// This sends a network message to the connection. /// </summary> /// <typeparam name="T">The message type</typeparam> /// <param name="msg">The message to send.</param> /// <param name="channelId">The transport layer channel to send on.</param> /// <returns></returns> public void Send <T>(T message, INotifyCallBack token) { if (isDisconnected) { return; } using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { MessagePacker.Pack(message, writer); var segment = writer.ToArraySegment(); NetworkDiagnostics.OnSend(message, segment.Count, 1); connection.SendNotify(segment, token); } }
/// <summary> /// This sends a network message to the connection. /// </summary> /// <typeparam name="T">The message type</typeparam> /// <param name="msg">The message to send.</param> /// <param name="channelId">The transport layer channel to send on.</param> /// <returns></returns> public void Send <T>(T message, int channelId = Channel.Reliable) { if (isDisconnected) { return; } using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { MessagePacker.Pack(message, writer); var segment = writer.ToArraySegment(); NetworkDiagnostics.OnSend(message, segment.Count, 1); Send(segment, channelId); } }
void CheckSendRate() { float now = Time.time; if (SendMessagesAllowed && syncInterval >= 0 && now > nextSendTime) { nextSendTime = now + syncInterval; using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { if (WriteParameters(writer)) { SendAnimationParametersMessage(writer.ToArray()); } } } }
void UpdateClient() { // send to server if we have local authority (and aren't the server) // -> only if connectionToServer has been initialized yet too // check only each 'syncInterval' if (!IsServer && IsClientWithAuthority && Time.time - lastClientSendTime >= syncInterval) { if (HasEitherMovedRotatedScaled()) { // serialize // local position/rotation for VR support using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { SerializeIntoWriter(writer, TargetComponent.localPosition, TargetComponent.localRotation, TargetComponent.localScale); // send to server CmdClientToServerSync(writer.ToArray()); } } lastClientSendTime = Time.time; } // apply interpolation on client for all players // unless this client has authority over the object. could be // himself or another object that he was assigned authority over if (!IsClientWithAuthority && goal != null) { // teleport or interpolate if (NeedsTeleport()) { // local position/rotation for VR support ApplyPositionRotationScale(goal.LocalPosition, goal.LocalRotation, goal.LocalScale); // reset data points so we don't keep interpolating start = null; goal = null; } else { // local position/rotation for VR support ApplyPositionRotationScale(InterpolatePosition(start, goal, TargetComponent.localPosition), InterpolateRotation(start, goal, TargetComponent.localRotation), InterpolateScale(start, goal, TargetComponent.localScale)); } } }
/// <summary> /// Sends a message to many connections /// <para> /// Same as <see cref="SendToMany{T}(IEnumerable{INetworkPlayer}, T, int)"/> but uses for loop to avoid allocations /// </para> /// </summary> /// <remarks> /// Using list in foreach loop causes Unity's mono version to box the struct which causes allocations, <see href="https://docs.unity3d.com/2019.4/Documentation/Manual/BestPracticeUnderstandingPerformanceInUnity4-1.html">Understanding the managed heap</see> /// </remarks> public static void SendToMany <T>(IReadOnlyList <INetworkPlayer> players, T msg, int channelId = Channel.Reliable) { using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { // pack message into byte[] once MessagePacker.Pack(msg, writer); var segment = writer.ToArraySegment(); int count = players.Count; for (int i = 0; i < count; i++) { players[i].Send(segment, channelId); } NetworkDiagnostics.OnSend(msg, segment.Count, count); } }
/// <summary> /// Sends a message to many connections /// </summary> /// <typeparam name="T"></typeparam> /// <param name="players"></param> /// <param name="msg"></param> /// <param name="channelId"></param> public static void SendToMany <T>(IEnumerable <INetworkPlayer> players, T msg, int channelId = Channel.Reliable) { using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { // pack message into byte[] once MessagePacker.Pack(msg, writer); var segment = writer.ToArraySegment(); int count = 0; foreach (INetworkPlayer player in players) { player.Send(segment, channelId); count++; } NetworkDiagnostics.OnSend(msg, segment.Count, count); } }
internal void SendSpawnMessage(NetworkIdentity identity, INetworkPlayer player) { if (logger.LogEnabled()) { logger.Log($"Server SendSpawnMessage: name={identity.name} sceneId={identity.SceneId:X} netId={identity.NetId}"); } // one writer for owner, one for observers using (PooledNetworkWriter ownerWriter = NetworkWriterPool.GetWriter(), observersWriter = NetworkWriterPool.GetWriter()) { var isOwner = identity.Owner == player; var payload = CreateSpawnMessagePayload(isOwner, identity, ownerWriter, observersWriter); var prefabHash = identity.IsPrefab ? identity.PrefabHash : default(int?); var sceneId = identity.IsSceneObject ? identity.SceneId : default(ulong?); var msg = new SpawnMessage { netId = identity.NetId, isLocalPlayer = player.Identity == identity, isOwner = isOwner, sceneId = sceneId, prefabHash = prefabHash, payload = payload, }; // values in msg are nullable, so by default they are null // only set those values if the identity's settings say to send them if (identity.SpawnSettings.SendPosition) { msg.position = identity.transform.localPosition; } if (identity.SpawnSettings.SendRotation) { msg.rotation = identity.transform.localRotation; } if (identity.SpawnSettings.SendScale) { msg.scale = identity.transform.localScale; } player.Send(msg); } }
public static void Send <T>(IEnumerable <INetworkConnection> connections, T msg, int channelId = Channel.Reliable) { using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { // pack message into byte[] once MessagePacker.Pack(msg, writer); var segment = writer.ToArraySegment(); int count = 0; foreach (INetworkConnection conn in connections) { // send to all connections, but don't wait for them conn.Send(segment, channelId); count++; } NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count); } }
static ArraySegment <byte> CreateSpawnMessagePayload(bool isOwner, NetworkIdentity identity, PooledNetworkWriter ownerWriter, PooledNetworkWriter observersWriter) { // Only call OnSerializeAllSafely if there are NetworkBehaviours if (identity.NetworkBehaviours.Length == 0) { return(default);