Beispiel #1
0
        /// <summary>
        /// Generate rigid body transform snapshot for owned transforms with specified timestamp.
        /// </summary>
        /// <param name="time">Snapshot timestamp.</param>
        /// <param name="rootTransform">Root transform.</param>
        /// <returns>Generated snapshot.</returns>
        public Snapshot GenerateSnapshot(float time, UnityEngine.Transform rootTransform)
        {
            // collect transforms from owned rigid bodies
            // and generate update packet/snapshot

            List <Snapshot.TransformInfo> transforms = new List <Snapshot.TransformInfo>(_rigidBodies.Count);

            foreach (var rb in _rigidBodies.Values)
            {
                if (!rb.Ownership)
                {
                    continue;
                }

                RigidBodyTransform transform;
                {
                    transform.Position = rootTransform.InverseTransformPoint(rb.RigidBody.transform.position);
                    transform.Rotation = UnityEngine.Quaternion.Inverse(rootTransform.rotation) * rb.RigidBody.transform.rotation;
                }

                Patching.Types.MotionType mType = (rb.IsKeyframed) ? (Patching.Types.MotionType.Keyframed)
                                        : (Patching.Types.MotionType.Dynamic);

                transforms.Add(new Snapshot.TransformInfo(rb.Id, transform, mType));
#if MRE_PHYSICS_DEBUG
                Debug.Log(" SEND Remote body: " + rb.Id.ToString() + " OriginalRot:" + transform.Rotation
                          + " RigidBodyRot:" + rb.RigidBody.transform.rotation);
#endif
            }

            return(new Snapshot(time, transforms));
        }
Beispiel #2
0
        /// <summary>
        /// Generate rigid body transform snapshot for owned transforms with specified timestamp.
        /// </summary>
        /// <param name="time">Snapshot timestamp.</param>
        /// <param name="rootTransform">Root transform.</param>
        /// <returns>Generated snapshot.</returns>
        public Snapshot GenerateSnapshot(float time, UnityEngine.Transform rootTransform)
        {
            // collect transforms from owned rigid bodies
            // and generate update packet/snapshot

            // these constants define when a body is considered to be sleeping
            const float globalToleranceMultipier        = 1.0F;
            const float maxSleepingSqrtLinearVelocity   = 0.1F * globalToleranceMultipier;
            const float maxSleepingSqrtAngularVelocity  = 0.1F * globalToleranceMultipier;
            const float maxSleepingSqrtPositionDiff     = 0.02F * globalToleranceMultipier;
            const float maxSleepingSqrtAngularEulerDiff = 0.15F * globalToleranceMultipier;

            const short limitNoUpdateForSleepingBodies = 500;
            const short numConsecutiveSleepingTrueConditionForNoUpdate = 5;

            int numSleepingBodies = 0;
            int numOwnedBodies    = 0;

            List <Snapshot.TransformInfo> transforms = new List <Snapshot.TransformInfo>(_rigidBodies.Count);

            foreach (var rb in _rigidBodies.Values)
            {
                if (!rb.Ownership)
                {
                    rb.numOfConsequentSleepingFrames = 0;
                    continue;
                }

                RigidBodyTransform transform;
                {
                    transform.Position = rootTransform.InverseTransformPoint(rb.RigidBody.transform.position);
                    transform.Rotation = UnityEngine.Quaternion.Inverse(rootTransform.rotation) * rb.RigidBody.transform.rotation;
                }

                numOwnedBodies++;
                Patching.Types.MotionType mType = (rb.IsKeyframed) ? (Patching.Types.MotionType.Keyframed)
                                        : (Patching.Types.MotionType.Dynamic);

                UnityEngine.Vector3 posDiff = rb.lastValidLinerVelocityOrPos - transform.Position;
                UnityEngine.Vector3 rotDiff = UtilMethods.TransformEulerAnglesToRadians(rb.lastValidAngularVelocityorAng - transform.Rotation.eulerAngles);

                bool isBodySleepingInThisFrame =
                    (!rb.IsKeyframed) &&                     // if body is key framed and owned then we should just feed the jitter buffer
                    (rb.RigidBody.velocity.sqrMagnitude < maxSleepingSqrtLinearVelocity &&
                     rb.RigidBody.angularVelocity.sqrMagnitude < maxSleepingSqrtAngularVelocity &&
                     posDiff.sqrMagnitude < maxSleepingSqrtPositionDiff &&
                     rotDiff.sqrMagnitude < maxSleepingSqrtAngularEulerDiff);

                if (isBodySleepingInThisFrame)
                {
                    rb.numOfConsequentSleepingFrames++;
                    rb.numOfConsequentSleepingFrames = (rb.numOfConsequentSleepingFrames > (short)limitNoUpdateForSleepingBodies) ?
                                                       (short)limitNoUpdateForSleepingBodies : rb.numOfConsequentSleepingFrames;
                }
                else
                {
                    rb.numOfConsequentSleepingFrames = 0;
                }

                // this is the real condition to put a body to sleep
                bool isBodySleeping = (rb.numOfConsequentSleepingFrames > numConsecutiveSleepingTrueConditionForNoUpdate);

                // test if this is sleeping, and when this was newly added then
                if (rb.lastTimeKeyFramedUpdate > 0.001F && isBodySleeping &&
                    rb.sendMotionType == Patching.Types.MotionType.Sleeping &&
                    rb.numOfConsequentSleepingFrames < limitNoUpdateForSleepingBodies)
                {
                    // condition for velocity and positions are triggered and we already told the consumers to make body sleep, so just skip this update
                    numSleepingBodies++;
                    continue;
                }

                mType = (isBodySleeping) ? (Patching.Types.MotionType.Sleeping) : mType;
                // here we handle the case when after of 300 frames with no update we should send one update at least
                if (rb.numOfConsequentSleepingFrames >= limitNoUpdateForSleepingBodies)
                {
                    rb.numOfConsequentSleepingFrames = numConsecutiveSleepingTrueConditionForNoUpdate + 1;
                }

                // store the last update informations
                rb.sendMotionType                = mType;
                rb.lastTimeKeyFramedUpdate       = time;
                rb.lastValidLinerVelocityOrPos   = transform.Position;
                rb.lastValidAngularVelocityorAng = transform.Rotation.eulerAngles;

                transforms.Add(new Snapshot.TransformInfo(rb.Id, transform, mType));
#if MRE_PHYSICS_DEBUG
                Debug.Log(" SEND Remote body: " + rb.Id.ToString() + " OriginalRot:" + transform.Rotation
                          + " RigidBodyRot:" + rb.RigidBody.transform.rotation
                          + " lv:" + rb.RigidBody.velocity + " av:" + rb.RigidBody.angularVelocity
                          + " posDiff:" + posDiff + " rotDiff:" + rotDiff + " isKeyF:" + rb.IsKeyframed);
#endif
            }

            Snapshot.SnapshotFlags snapshotFlag = Snapshot.SnapshotFlags.NoFlags;

            bool allBodiesAreSleepingNew = numOwnedBodies == numSleepingBodies;
            if (allBodiesAreSleepingNew != _allOwnedBodiesAreSleeping)
            {
                _allOwnedBodiesAreSleeping = allBodiesAreSleepingNew;
                snapshotFlag = Snapshot.SnapshotFlags.ResetJitterBuffer;
            }

            _lastNumberOfTransformsToBeSent = numOwnedBodies;

            var ret = new Snapshot(time, transforms, snapshotFlag);

#if MRE_PHYSICS_DEBUG
            Debug.Log(" Client:" + " Total number of sleeping bodies: " + numSleepingBodies + " total RBs" + _rigidBodies.Count
                      + " num owned " + numOwnedBodies + " num sent transforms " + transforms.Count
                      + " send:" + ret.DoSendThisSnapshot());
#endif

            return(ret);
        }