// Receive transform
        void ModelDidRead(RealtimeTransformModel model)
        {
            if (model != _model)
            {
                Debug.LogError("RealtimeTransform received model didRead event from another model... This is a bug.");
                return;
            }

            // If it's owned by us, ignore the event.
            if (isOwnedLocally)
            {
                return;
            }

            // Used to keep the value consistent after ownership change (also means the editor reflects the current state for remote transforms).
            _extrapolation = _model.shouldExtrapolate;

            // We've received a new frame, stop simulating locally now that we have more information on the collision.
            _stopExtrapolatingAtRoomTime = -1.0f;
        }
        // Send transform
        private void ModelWillWrite(RealtimeTransformModel model)
        {
            if (model != _model)
            {
                Debug.LogError("RealtimeTransform received model willWrite event from another model... This is a bug.");
                return;
            }

            // If it's not owned by us, ignore the event.
            if (!isOwnedLocally)
            {
                return;
            }

            // We own this RealtimeTransform. Update the model to reflect its current position.
            if (_rigidbody != null)
            {
                if (_syncPosition)
                {
                    _model.position = _rigidbody.position;
                }
                if (_syncRotation)
                {
                    _model.rotation = _rigidbody.rotation;
                }
                if (_syncScale)
                {
                    _model.scale = transform.localScale;
                }
                if (_syncPosition)
                {
                    _model.velocity = _rigidbody.velocity;
                }
                if (_syncRotation)
                {
                    _model.angularVelocity = _rigidbody.angularVelocity;
                }
                //if (_shouldSyncScale) _model.scaleVelocity   =  // ...
                _model.useGravity  = _rigidbody.useGravity;
                _model.isKinematic = _rigidbody.isKinematic;
            }
            else
            {
                if (_syncPosition)
                {
                    _model.position = transform.localPosition;
                }
                if (_syncRotation)
                {
                    _model.rotation = transform.localRotation;
                }
                if (_syncScale)
                {
                    _model.scale = transform.localScale;
                }
            }

            if (_model.ModelPoseChangesToSend())
            {
                // Only send the timestamp if we're sending other pose changes.
                _model.timestamp = realtime.room.time;
                _wrotePoseChangesLastNetworkFrame = true;
            }
            else if (_wrotePoseChangesLastNetworkFrame)
            {
                // If we wrote changes last frame, but this frame the model is clean. Force one more model update to go out so extrapolation calculates a zero velocity.
                _model.timestamp = realtime.room.time;
            }

            // If the rigidbody has come to rest, clear ownership
            if (_rigidbody != null && _rigidbody.IsSleeping() && !_rigidbody.isKinematic)
            {
                _model.ClearOwnership();
            }

            // Set should extrapolate flag
            _model.shouldExtrapolate = _extrapolation;
        }
        void SetModel(RealtimeTransformModel model)
        {
            if (_model != null)
            {
                // Clear events
                _model.willWrite -= ModelWillWrite;
                _model.didRead   -= ModelDidRead;
            }

            _model = model;

            if (_model != null)
            {
                // Register for events
                _model.willWrite += ModelWillWrite;
                _model.didRead   += ModelDidRead;

                _model.shouldWritePosition         = _syncPosition;
                _model.shouldWriteRotation         = _syncRotation;
                _model.shouldWriteScale            = _syncScale;
                _model.shouldWriteVelocityMetadata = _rigidbody != null;

                // Sync with the model
                if (_model.freshModel)
                {
                    // If this is a fresh model, fill it with the current transform state
                    if (_rigidbody != null)
                    {
                        if (_syncPosition)
                        {
                            _model.position = _rigidbody.position;
                        }
                        if (_syncRotation)
                        {
                            _model.rotation = _rigidbody.rotation;
                        }
                        if (_syncScale)
                        {
                            _model.scale = transform.localScale;
                        }
                        if (_syncPosition)
                        {
                            _model.velocity = _rigidbody.velocity;
                        }
                        if (_syncRotation)
                        {
                            _model.angularVelocity = _rigidbody.angularVelocity;
                        }
                        //if (_shouldSyncScale)    _model.scaleVelocity   =  // ...
                        if (_rigidbody != null)
                        {
                            _model.useGravity = _rigidbody.useGravity;
                        }
                        if (_rigidbody != null)
                        {
                            _model.isKinematic = _rigidbody.isKinematic;
                        }
                    }
                    else
                    {
                        if (_syncPosition)
                        {
                            _model.position = transform.localPosition;
                        }
                        if (_syncRotation)
                        {
                            _model.rotation = transform.localRotation;
                        }
                        if (_syncScale)
                        {
                            _model.scale = transform.localScale;
                        }
                    }
                }
                else
                {
                    // If this is not a fresh model, set the transform using the model
                    if (_rigidbody != null)
                    {
                        if (_syncScale)
                        {
                            transform.localScale = _model.scale;
                        }
                        if (_syncPosition)
                        {
                            _rigidbody.position = _model.position;
                        }
                        if (_syncRotation)
                        {
                            _rigidbody.rotation = _model.rotation;
                        }
                        if (_syncPosition)
                        {
                            _rigidbody.velocity = _model.velocity;
                        }
                        if (_syncRotation)
                        {
                            _rigidbody.angularVelocity = _model.angularVelocity;
                        }
                        if (_rigidbody != null)
                        {
                            _rigidbody.useGravity = _model.useGravity;
                        }
                        if (_rigidbody != null)
                        {
                            _rigidbody.isKinematic = _model.isKinematic;
                        }
                    }
                    else
                    {
                        if (_syncPosition)
                        {
                            transform.localPosition = _model.position;
                        }
                        if (_syncRotation)
                        {
                            transform.localRotation = _model.rotation;
                        }
                        if (_syncScale)
                        {
                            transform.localScale = _model.scale;
                        }
                    }
                }
            }
        }