byte[] Serialize() { serializationBytes.Clear(); VoosNetworkTypes.ShortToBytes stb = new VoosNetworkTypes.ShortToBytes(); VoosNetworkTypes.UintToBytes utb = new VoosNetworkTypes.UintToBytes(); int totalCount = 0; float totalProbability = 0; foreach (KeyValuePair <short, NetworkedActor> na in actors) { VoosActor va = na.Value.actor; if (va != null && va.reliablePhotonView.isMine && !va.IsParented()) { Vector3 p = va.transform.position; Quaternion q = va.transform.rotation; if (na.Value.lastPosition != p || na.Value.lastRotation != q || na.Value.lastColor != va.GetTint()) { na.Value.lastPosition = p; na.Value.lastRotation = q; na.Value.lastColor = va.GetTint(); na.Value.lastTransformUpdateFrame = Time.frameCount; na.Value.messagesSinceLastUpdate = 0; } na.Value.updateProbability = Mathf.Clamp(1.0f / (float)(1 + na.Value.messagesSinceLastUpdate), minimumProbabilityOfUpdate, 1); totalProbability += na.Value.updateProbability; } totalCount++; } float probabilityOfPositionUpdate = 1; if (totalCount > MaxPositionUpdatesPerTick) { probabilityOfPositionUpdate = (float)MaxPositionUpdatesPerTick / totalProbability; } /// Message Header /// Transform count - will modify after the fact. serializationBytes.Add(0); serializationBytes.Add(0); /// Timestamp for prediction. utb.data = VoosNetworkTypes.CompressFloatToUint24(Time.time); serializationBytes.Add(utb.byte0); serializationBytes.Add(utb.byte1); serializationBytes.Add(utb.byte2); int index = 0; foreach (KeyValuePair <short, NetworkedActor> na in actors) { VoosActor va = na.Value.actor; if (va != null && va.reliablePhotonView.isMine && !va.IsParented()) { if (Random.value > (probabilityOfPositionUpdate * na.Value.updateProbability)) { continue; } na.Value.messagesSinceLastUpdate++; /// View ID stb.data = (short)va.reliablePhotonView.viewID; serializationBytes.Add(stb.byte0); serializationBytes.Add(stb.byte1); /// Network data bitmask UnreliableBitmask mask = UnreliableBitmask.None; mask |= va.GetTeleport() ? UnreliableBitmask.Teleport : UnreliableBitmask.None; mask |= va.GetEnablePhysics() ? UnreliableBitmask.EnablePhysics : UnreliableBitmask.None; serializationBytes.Add((byte)mask); // Unset the "teleport" flag, as it's transient and should only be used for one network packet. va.SetTeleport(false); // SUBTLE: If physics is not enabled, then pos/rot is not likely to // change. However, any inaccuracies are also more likely to be noticed // (such as static walls being slightly tilted). So given this, always // send full precision updates for static objects. Sure, this is less // efficient for things like moving platforms which do not have physics // but often change, but that's likely to be a minority. /// Local Position utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.x)); utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.y)); utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.z)); // Static - send full precision rotation on change. TODO I'm sure // there's some way to compress it to 8 bytes without loss. var ftb = new VoosNetworkTypes.FloatToBytes(); Quaternion q = na.Value.lastRotation; ftb.SerializeTo(serializationBytes, q.x); ftb.SerializeTo(serializationBytes, q.y); ftb.SerializeTo(serializationBytes, q.z); ftb.SerializeTo(serializationBytes, q.w); //Color serializationBytes.Add(na.Value.lastColor.r); serializationBytes.Add(na.Value.lastColor.g); serializationBytes.Add(na.Value.lastColor.b); serializationBytes.Add(na.Value.lastColor.a); /// Linear Velocity Rigidbody rb = va.GetComponent <Rigidbody>(); Vector3 lv = Vector3.zero; if (rb != null && !rb.isKinematic) { lv = rb.velocity; } utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.x); serializationBytes.Add(utb.byte0); serializationBytes.Add(utb.byte1); serializationBytes.Add(utb.byte2); utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.y); serializationBytes.Add(utb.byte0); serializationBytes.Add(utb.byte1); serializationBytes.Add(utb.byte2); utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.z); serializationBytes.Add(utb.byte0); serializationBytes.Add(utb.byte1); serializationBytes.Add(utb.byte2); index++; } } stb.data = (short)index; serializationBytes[0] = stb.byte0; serializationBytes[1] = stb.byte1; if (index == 0) { return(null); } return(serializationBytes.ToArray()); }