Пример #1
0
        private void PrepareForGameplay(ReplayInitialDataBuffer initialStateBuffer)
        {
            // Check if we can restore the previous scene state
            if (prePlaybackState != null)
            {
                // Restore the original game state
                if (restorePreviousSceneState == true)
                {
                    RestoreSnapshot(prePlaybackState, initialStateBuffer);
                }

                // Reset to null so that next states are saved
                prePlaybackState = null;

                // Set delta so that changes are immediate
                ReplayTime.Delta = 1;

                // Be sure to update so interpolated objects can also update
                ReplayBehaviour.Events.CallReplayUpdateEvents();
            }

            for (int i = 0; i < replayObjects.Count; i++)
            {
                ReplayManager.Preparer.PrepareForGameplay(replayObjects[i]);
            }
        }
Пример #2
0
        private void PrepareForPlayback(ReplayInitialDataBuffer initialStateBuffer)
        {
            // Sample the current scene
            prePlaybackState = RecordSnapshot(0, initialStateBuffer);

            for (int i = 0; i < replayObjects.Count; i++)
            {
                // Prepare the object for playback
                ReplayManager.Preparer.PrepareForPlayback(replayObjects[i]);
            }
        }
        /// <summary>
        /// Use this method to begin sampling the recorded objects in the scene.
        /// If <see cref="recordOnStart"/> is true then this method will be called automatically when the manager is initialized.
        /// Any state information will be recored via the assigned <see cref="ReplayTarget"/> (Default <see cref="ReplayMemoryTarget"/>).
        /// <param name="cleanRecording">When true, any previous recording data will be discarded</param>
        /// </summary>
        public static void BeginRecording(bool cleanRecording = true)
        {
            // Make sure we have a manager
            if (Instance == null)
            {
                return;
            }

            // Throw away any leftover recording data
            if (cleanRecording == true)
            {
                DiscardRecording();
            }

            // Check if we are replaying
            if (IsReplaying == true)
            {
                StopPlayback();
            }

            // Inform the replay target that we are about to begin recording
            Target.PrepareTarget(ReplayTargetTask.PrepareWrite);



            if (instance.state != PlaybackState.Recording_Paused)
            {
                // Reset the record timer
                Instance.recordStepTimer.Reset();
                Instance.recordTimer.Reset();


                // Every recording must begin with a frame that has a time stamp of 0
                ReplaySnapshot currentState = Instance.scene.RecordSnapshot(0, Target.InitialStateBuffer);

                // Write it to the replay target
                Target.RecordSnapshot(currentState);
            }

            // Change to recording state
            Instance.state = PlaybackState.Recording;
        }
Пример #4
0
        /// <summary>
        /// Take a snapshot of the current replay scene using the specified timestamp.
        /// </summary>
        /// <param name="timeStamp">The timestamp for the frame indicating its position in the playback sequence</param>
        /// <param name="initialStateBuffer">The <see cref="ReplayInitialDataBuffer"/> to restore dynamic object information from</param>
        /// <returns>A new snapshot of the current replay scene</returns>
        public ReplaySnapshot RecordSnapshot(float timeStamp, ReplayInitialDataBuffer initialStateBuffer)
        {
            ReplaySnapshot snapshot = new ReplaySnapshot(timeStamp);

            if (initialStateBuffer != null)
            {
                // Be sure to record any objects initial transform if they were spawned during the snapshot
                while (dynamicReplayObjects.Count > 0)
                {
                    // Get the next object
                    ReplayObject obj = dynamicReplayObjects.Dequeue();

                    // Make sure the object has not been destroyed
                    if (obj != null)
                    {
                        // Record initial values
                        initialStateBuffer.RecordInitialReplayObjectData(obj, timeStamp, obj.transform.position, obj.transform.rotation, obj.transform.localScale);
                    }
                }
            }


            // Record each object in the scene
            foreach (ReplayObject obj in replayObjects)
            {
                ReplayState state = new ReplayState();

                // Serialize the object
                obj.OnReplaySerialize(state);

                // Check if the state contains any information - If not then dont waste valuable memory
                if (state.Size == 0)
                {
                    continue;
                }

                // Record the snapshot
                snapshot.RecordSnapshot(obj.ReplayIdentity, state);
            }

            return(snapshot);
        }
Пример #5
0
        /// <summary>
        /// Restore the scene to the state described by the specified snapshot.
        /// </summary>
        /// <param name="snapshot">The snapshot to restore</param>
        /// <param name="initialStateBuffer">The <see cref="ReplayInitialDataBuffer"/> to restore dynamic object information from</param>
        public void RestoreSnapshot(ReplaySnapshot snapshot, ReplayInitialDataBuffer initialStateBuffer)
        {
            // Restore all events first
            snapshot.RestoreReplayObjects(this, initialStateBuffer);

            // Restore all replay objects
            foreach (ReplayObject obj in replayObjects)
            {
                // Get the state based on the identity
                ReplayState state = snapshot.RestoreSnapshot(obj.ReplayIdentity);

                // Check if no state information for this object was found
                if (state == null)
                {
                    continue;
                }

                // Deserialize the object
                obj.OnReplayDeserialize(state);
            }
        }
        /// <summary>
        /// Use this method to specify where in the replay sequence the playback should start.
        /// This method accepts normalized offsets values between 0 and 1 and performs validation before using the value.
        /// </summary>
        /// <param name="normalizedOffset">The normalized value representing the offset from the specified origin to start the playback from</param>
        /// <param name="origin">The playback node to take the offset from. If <see cref="PlaybackOrigin.End"/> is specified then the offset value will be used as a negative offset</param>
        public static void SetPlaybackFrameNormalized(float normalizedOffset, PlaybackOrigin origin = PlaybackOrigin.Start)
        {
            // Make sure we have a manager
            if (Instance == null)
            {
                return;
            }

            // Move our current sequence frame to the normalized value
            ReplaySnapshot frame = Instance.sequence.SeekPlayback(normalizedOffset, origin, true);

            // Check for a valid frame
            if (frame != null)
            {
                // Restore the scene state
                Instance.scene.RestoreSnapshot(frame, Target.InitialStateBuffer);

                // Call the reset event
                ReplayBehaviour.Events.CallReplayResetEvents();

                // This calls 'updateReplay' on all replay obejcts in the scene
                ReplayBehaviour.Events.CallReplayUpdateEvents();
            }
        }
        /// <summary>
        /// The main update method of the replay manager.
        /// Causes the replay manager to update its state based on the current <see cref="state"/>.
        /// </summary>
        /// <param name="deltaTime"></param>
        public void UpdateState(float deltaTime)
        {
            if (deltaTime <= 0f)
            {
                Debug.Log(Time.timeScale);
                throw new InvalidOperationException("Delta time value must be greater than '0'");
            }

            switch (state)
            {
            case PlaybackState.Idle: break;

            case PlaybackState.Playback_Paused: break;     // Do nothing

            case PlaybackState.Recording_Paused: break;    // Do nothing

            case PlaybackState.Recording_Paused_Playback:
            case PlaybackState.Playback:
            {
                // Make sure we are not in single frame mode
                if (singlePlayback == false)
                {
                    ReplaySnapshot frame;

                    // Update the sequencer
                    ReplaySequenceResult result = sequence.UpdatePlayback(out frame, playbackEndBehaviour, deltaTime);

                    // Check if the sequence has a new frame to be displayed
                    if (result == ReplaySequenceResult.SequenceAdvance)
                    {
                        // Restore the scene state
                        scene.RestoreSnapshot(frame, Target.InitialStateBuffer);
                    }
                    // Check if the sequence is at the end of the recording
                    else if (result == ReplaySequenceResult.SequenceEnd)
                    {
                        StopPlayback();
                    }

                    // Update the playback
                    if (result == ReplaySequenceResult.SequenceIdle ||
                        result == ReplaySequenceResult.SequenceAdvance)
                    {
                        // This calls 'updateReplay' on all replay obejcts in the scene
                        ReplayBehaviour.Events.CallReplayUpdateEvents();
                    }
                }
            } break;

            case PlaybackState.Recording:
            {
                // Update the replay timer - Pass the delta time instead of using Time.deltaTime
                ReplayTimer.Tick(deltaTime);

                // Make sure enough time has passed to record a sample
                if (recordStepTimer.HasElapsed() == true)
                {
                    // Get the scene state
                    ReplaySnapshot currentState = scene.RecordSnapshot(Instance.recordTimer.ElapsedSeconds, Target.InitialStateBuffer);

                    // Write it to the replay target
                    Target.RecordSnapshot(currentState);
                }
            } break;
            }
        }
Пример #8
0
        // Methods
        public ReplaySnapshot SeekPlayback(float offset, PlaybackOrigin origin, bool normalized)
        {
            // Check for normalized
            if (normalized == false)
            {
                // Check for seek mode
                switch (origin)
                {
                case PlaybackOrigin.Start:
                    playbackTime = offset;
                    break;

                case PlaybackOrigin.End:
                    playbackTime = target.Duration - offset;
                    break;

                case PlaybackOrigin.Current:
                    playbackTime += offset;
                    break;
                }
            }
            else
            {
                // Clamp the input valid
                offset = Mathf.Clamp01(offset);

                // Check for seek mode
                switch (origin)
                {
                case PlaybackOrigin.Start:
                    playbackTime = MapScale(offset, 0, 1, 0, target.Duration);
                    break;

                case PlaybackOrigin.End:
                    playbackTime = MapScale(offset, 1, 0, 0, target.Duration);
                    break;

                case PlaybackOrigin.Current:
                    playbackTime = MapScale(offset, 0, 1, playbackTime, target.Duration);
                    break;
                }
            }

            // Clamp to valid range
            playbackTime = Mathf.Clamp(playbackTime, 0, target.Duration);

            // Restore the scene state
            current = target.RestoreSnapshot(playbackTime);

            // Check for change
            if (current != last)
            {
                // Update the replay time
                ReplayTime.Time = playbackTime;

                if (last != null && current != null)
                {
                    // Check for backwards
                    if (last.TimeStamp <= current.TimeStamp)
                    {
                        // Forward
                        ReplayTime.Delta = MapScale(playbackTime, last.TimeStamp, current.TimeStamp, 0, 1);
                    }
                    else
                    {
                        // Backward
                        ReplayTime.Delta = -MapScale(playbackTime, last.TimeStamp, current.TimeStamp, 1, 0);
                    }
                }
            }
            //else
            //{
            //    ReplayTime.Delta = 0;
            //}

            // Store current frame
            last = current;

            return(current);
        }
Пример #9
0
        public ReplaySequenceResult UpdatePlayback(out ReplaySnapshot frame, PlaybackEndBehaviour endBehaviour, float deltaTime)
        {
            PlaybackDirection direction = ReplayTime.TimeScaleDirection;

            // Default to idle
            ReplaySequenceResult result = ReplaySequenceResult.SequenceIdle;

            if (last != null)
            {
                if (direction == PlaybackDirection.Forward)
                {
                    // Calculatet the delta time
                    ReplayTime.Delta = MapScale(playbackTime, last.TimeStamp, current.TimeStamp, 0, 1);
                }
                else
                {
                    // Calculate the delta for reverse playback
                    ReplayTime.Delta = -MapScale(playbackTime, current.TimeStamp, last.TimeStamp, 0, 1);
                }
            }
            else
            {
                if (current == null)
                {
                    ReplayTime.Delta = 0;
                }
                else
                {
                    ReplayTime.Delta = MapScale(playbackTime, 0, current.TimeStamp, 0, 1);
                }
            }

            // Clamp delta
            ReplayTime.Delta = Mathf.Clamp01(ReplayTime.Delta);

            float delta = Mathf.Abs(deltaTime * ReplayTime.TimeScale);

            //if (fixedTime == true)
            //{
            //    // Find the fixed time delta
            //    delta = (Time.fixedDeltaTime * ReplayTime.TimeScale);
            //}
            //else
            //{
            //    // Find the time delta
            //    delta = (Time.deltaTime * Mathf.Abs(ReplayTime.TimeScale));
            //}

            // Advance our frame
            switch (direction)
            {
            case PlaybackDirection.Forward:
            {
                playbackTime += delta;
            }
            break;

            case PlaybackDirection.Backward:
            {
                playbackTime -= delta;
            }
            break;
            }

            switch (endBehaviour)
            {
            default:
            case PlaybackEndBehaviour.EndPlayback:
            {
                // Check for end of playback
                if (playbackTime >= target.Duration || playbackTime < 0)
                {
                    frame = null;
                    return(ReplaySequenceResult.SequenceEnd);
                }
                break;
            }

            case PlaybackEndBehaviour.LoopPlayback:
            {
                if (playbackTime >= target.Duration || playbackTime < 0)
                {
                    playbackTime = (direction == PlaybackDirection.Forward) ? 0 : target.Duration;
                }
                break;
            }

            case PlaybackEndBehaviour.StopPlayback:
            {
                if (playbackTime >= target.Duration)
                {
                    playbackTime = target.Duration;
                }
                else if (playbackTime < 0)
                {
                    playbackTime = 0;
                }
                break;
            }
            }


            // Try to get the current frame
            ReplaySnapshot temp = target.RestoreSnapshot(playbackTime);

            // Check for valid frame
            if (temp != null)
            {
                // Check for sequence advancement
                if (current != temp)
                {
                    // Snap to next frame
                    ReplayTime.Delta = 0;

                    // Set the result
                    result = ReplaySequenceResult.SequenceAdvance;

                    // Update last frame
                    last = current;
                }

                // Update the current frame
                current = temp;
            }
            else
            {
                // Do nothing - We may be inbetween replay frames

                // Trigger sequence end
                //frame = null;
                //return ReplaySequenceResult.SequenceEnd;
            }

            // The sequencer only updated its timing values and there was no state change
            frame = current;
            return(result);
        }