void Update()
        {
            // if server then always sync to others.
            if (isServer)
            {
                // just use OnSerialize via SetDirtyBit only sync when position
                // changed. set dirty bits 0 or 1
                SetDirtyBit(HasMovedOrRotated() ? 1UL : 0UL);
            }

            // no 'else if' since host mode would be both
            if (isClient)
            {
                // send to server if we have local authority (and aren't the server)
                // -> only if connectionToServer has been initialized yet too
                if (!isServer && hasAuthority && connectionToServer != null)
                {
                    // check only each 'syncInterval'
                    if (Time.time - lastClientSendTime >= syncInterval)
                    {
                        if (HasMovedOrRotated())
                        {
                            // serialize
                            NetworkWriter writer = new NetworkWriter();
                            SerializeIntoWriter(writer, targetComponent.transform.position, targetComponent.transform.rotation, compressRotation);

                            // send message to server
                            TransformMessage message = new TransformMessage();
                            message.netId          = netId;
                            message.componentIndex = componentIndex;
                            message.payload        = writer.ToArray();
                            connectionToServer.Send((short)MsgType.LocalPlayerTransform, message);
                        }
                        lastClientSendTime = Time.time;
                    }
                }

                // apply interpolation on client for all players
                // except for local player if he has authority and handles it himself
                if (!(isLocalPlayer && hasAuthority))
                {
                    // received one yet? (initialized?)
                    if (goal != null)
                    {
                        // teleport or interpolate
                        if (NeedsTeleport())
                        {
                            ApplyPositionAndRotation(goal.position, goal.rotation);
                        }
                        else
                        {
                            ApplyPositionAndRotation(InterpolatePosition(start, goal, targetComponent.transform.position),
                                                     InterpolateRotation(start, goal, targetComponent.transform.rotation));
                        }
                    }
                }
            }
        }
        // local authority client sends sync message to server for broadcasting
        // note: message is registered in NetworkServer.RegisterMessageHandlers
        //       because internal messages can't be registered from the outside
        // TODO make this a [Command] later (Weaver can't weave this as long as
        //      it's still in the same DLL)
        public static void OnClientToServerSync(NetworkMessage netMsg)
        {
            // read message
            TransformMessage message = netMsg.ReadMessage <TransformMessage>();

            // find that NetworkIdentity
            NetworkIdentity identity;

            if (!NetworkIdentity.spawned.TryGetValue(message.netId, out identity))
            {
                Debug.LogError("Received NetworkTransform data for GameObject that doesn't exist");
                return;
            }

            NetworkTransformBase[] foundSyncs = identity.GetComponents <NetworkTransformBase>();
            if (foundSyncs == null || foundSyncs.Length == 0 || message.componentIndex > foundSyncs.Length - 1)
            {
                Debug.LogError("HandleTransform null target");
                return;
            }

            NetworkTransformBase foundSync = foundSyncs[message.componentIndex];

            if (!foundSync.localPlayerAuthority)
            {
                Debug.LogError("HandleTransform no localPlayerAuthority");
                return;
            }

            if (netMsg.conn.clientOwnedObjects == null)
            {
                Debug.LogError("HandleTransform object not owned by connection");
                return;
            }

            if (netMsg.conn.clientOwnedObjects.Contains(message.netId))
            {
                // deserialize payload
                NetworkReader reader = new NetworkReader(message.payload);
                foundSync.DeserializeFromReader(reader);

                // server-only mode does no interpolation to save computations,
                // but let's set the position directly
                if (foundSync.isServer && !foundSync.isClient)
                {
                    foundSync.ApplyPositionAndRotation(foundSync.goal.position, foundSync.goal.rotation);
                }

                // set dirty so that OnSerialize broadcasts it
                foundSync.SetDirtyBit(1UL);
            }
            else
            {
                Debug.LogWarning("HandleTransform netId:" + message.netId + " is not for a valid player");
            }
        }