// Methods
        public IEnumerator Start()
        {
            // Usually you should register replay prefabs in editor via the global settings but it can also be done via code if required
            UltimateReplay.Settings.prefabs.RegisterReplayablePrefab(instanitatePrefab);


            // Start recording - Note that we need to enable 'allowEmptyScene' if there are no replay objects in the scene initially
            ReplayHandle recordHandle = ReplayManager.BeginRecording(null, null, true, true);

            // Wait for some time to pass
            yield return(new WaitForSeconds(1f));

            // Spawn a dynamic replay object
            ReplayObject obj = Instantiate(instanitatePrefab);

            // Add the object to all recording scenes - This is a required step otherwise the object will not be recorded
            ReplayManager.AddReplayObjectToRecordScenes(obj);

            // Wait for some time to pass now that the object has been spawned
            yield return(new WaitForSeconds(1));

            // End recording
            // The resulting replay will have 1 second of nothing and then the dynamic object will be re-instantiated by the replay system
            ReplayManager.StopRecording(ref recordHandle);
        }
Пример #2
0
        void ILoadableContent.Load()
        {
            _object = ReplaysManager.Instance.GetById(_id);

            if (_object?.TrackId != null)
            {
                var trackObject = TracksManager.Instance.GetById(_object.TrackId);
                if (_object.TrackConfiguration != null)
                {
                    _trackObject = trackObject?.GetLayoutByLayoutId(_object.TrackConfiguration) ?? trackObject;
                }
                else
                {
                    _trackObject = trackObject;
                }
            }

            if (_object?.CarId != null)
            {
                _carObject     = CarsManager.Instance.GetById(_object.CarId);
                _carSkinObject = _carObject == null ? null :
                                 (_object.CarSkinId != null ? _carObject.SkinsManager.GetById(_object.CarSkinId) : null) ?? _carObject.SelectedSkin;
            }

            if (_object?.WeatherId != null)
            {
                _weather = WeatherManager.Instance.GetById(_object.WeatherId);
            }
        }
        // Methods
        public IEnumerator Start()
        {
            // Create a record scene for the record object
            ReplayScene recordScene = new ReplayScene(recordObject);

            // Start recording the single object
            ReplayHandle recordHandle = ReplayManager.BeginRecording(null, recordScene);

            // Allow some data to be recorded for 1 second
            yield return(new WaitForSeconds(1f));

            // Stop recording
            ReplayManager.StopRecording(ref recordHandle);


            // Clone the identity which allows the replayObject to be replayed as the recordObject
            ReplayObject.CloneReplayObjectIdentity(recordObject, replayObject);


            // Create a playback scene for the replay object
            ReplayScene playbackScene = new ReplayScene(replayObject);

            // Start playback
            ReplayManager.BeginPlayback(null, playbackScene);
        }
Пример #4
0
        async Task ILoadableContent.LoadAsync(CancellationToken cancellationToken)
        {
            _object = await ReplaysManager.Instance.GetByIdAsync(_id);

            if (_object?.TrackId != null)
            {
                var trackObject = await TracksManager.Instance.GetByIdAsync(_object.TrackId);

                if (_object.TrackConfiguration != null)
                {
                    _trackObject = trackObject?.GetLayoutByLayoutId(_object.TrackConfiguration) ?? trackObject;
                }
                else
                {
                    _trackObject = trackObject;
                }
            }

            if (_object?.CarId != null)
            {
                _carObject = await CarsManager.Instance.GetByIdAsync(_object.CarId);

                _carSkinObject = _carObject == null ? null :
                                 (_object.CarSkinId != null ? await _carObject.SkinsManager.GetByIdAsync(_object.CarSkinId) : null) ?? _carObject.SelectedSkin;
            }

            if (_object?.WeatherId != null)
            {
                _weather = await WeatherManager.Instance.GetByIdAsync(_object.WeatherId);
            }
        }
Пример #5
0
 /// <summary>
 /// Unregisters a replay object from the replay system so that it will no longer be recorded for playback.
 /// Typically all <see cref="ReplayObject"/> will auto un-register when they are destroyed so you will normally not need to un-register a replay object.
 /// </summary>
 /// <param name="replayObject"></param>
 public void UnregisterReplayObject(ReplayObject replayObject)
 {
     // Remove the replay object
     if (replayObjects.Contains(replayObject) == true)
     {
         replayObjects.Remove(replayObject);
     }
 }
Пример #6
0
        public void RecordInitialReplayObjectData(ReplayObject obj, float timestamp, Vector3 position, Quaternion rotation, Vector3 scale)
        {
            // Create the initial data
            ReplayInitialData data = new ReplayInitialData();

            // Store the object identity
            data.objectIdentity = obj.ReplayIdentity;
            data.timestamp      = timestamp;

            // Store the transform information
            data.position = position;
            data.rotation = rotation;
            data.scale    = scale;

            // Store the parent identities
            if (obj.transform.parent != null)
            {
                // Get the parent replay object
                ReplayObject replayParent = obj.transform.parent.GetComponent <ReplayObject>();

                // Store parent identity
                if (replayParent != null)
                {
                    data.parentIdentity = replayParent.ReplayIdentity;
                }
            }


            // Store observed component identity array
            int size  = obj.ObservedComponentsCount;
            int index = 0;

            // Allocate array
            data.observedComponentIdentities = new ReplayIdentity[size];

            foreach (ReplayBehaviour behaviour in obj.ObservedComponents)
            {
                // Store component identity in array
                data.observedComponentIdentities[index] = behaviour.Identity;
                index++;
            }


            // Update stored data flags
            data.UpdateDataFlags();


            // Register the initial data with the corrosponding identity
            if (initialStates.ContainsKey(obj.ReplayIdentity) == false)
            {
                initialStates.Add(obj.ReplayIdentity, new List <ReplayInitialData>());
            }

            // Store the state data
            initialStates[obj.ReplayIdentity].Add(data);
        }
Пример #7
0
        // Methods
        /// <summary>
        /// Prepare the specified replay object for playback mode.
        /// </summary>
        /// <param name="replayObject">The replay object to prepare</param>
        public virtual void PrepareForPlayback(ReplayObject replayObject)
        {
            // Find all components on the object
            foreach (Component component in replayObject.GetComponentsInChildren <Component>())
            {
                // Make sure the component is still alive
                if (component == null)
                {
                    return;
                }

                bool skip = false;

                // Check if the component should be prepared or skipped
                foreach (Type skipType in skipTypes)
                {
                    // Check if the component is a skip type or child of
                    if (skipType.IsInstanceOfType(component))
                    {
                        // Set the skip flag
                        skip = true;
                        break;
                    }
                }

                // Check if we should skip the component
                if (skip == true)
                {
                    continue;
                }

                // Get the component type
                Type componentType = component.GetType();

                // Try to find a preparer
                ComponentPreparer preparer = FindPreparer(componentType);

                // Check for error
                if (preparer == null)
                {
                    continue;
                }

                // Prepare the component
                preparer.InvokePrepareForPlayback(component);
            }
        }
Пример #8
0
        // Methods
        /// <summary>
        /// Registers a replay object with the replay system so that it can be recorded for playback.
        /// Typically all <see cref="ReplayObject"/> will auto register when they 'Awake' meaning that you will not need to manually register objects.
        /// </summary>
        /// <param name="replayObject">The <see cref="ReplayObject"/> to register</param>
        public void RegisterReplayObject(ReplayObject replayObject)
        {
            // Add the replay object
            replayObjects.Add(replayObject);

            // Check if we are adding objects during playback
            if (isPlayback == true)
            {
                // We need to prepare the object for playback
                ReplayManager.Preparer.PrepareForPlayback(replayObject);
            }
            // Check if we are adding objects during recording
            else// if(ReplayManager.IsRecording == true)
            {
                // The object was added during recording
                dynamicReplayObjects.Enqueue(replayObject);
            }
        }
Пример #9
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);
        }
Пример #10
0
        public void OnTriggerEnter(Collider other)
        {
            Debug.LogWarning("Trigger");

            // Stop replaying
            if (ReplayManager.IsReplaying(playbackHandle) == true)
            {
                ReplayManager.StopPlayback(ref playbackHandle);
            }

            // Stop recording
            if (ReplayManager.IsRecording(recordHandle) == true)
            {
                // Stop recording
                ReplayManager.StopRecording(ref recordHandle);

                playbackStorage = recordStorage;
                recordStorage   = new ReplayMemoryTarget();

                Debug.Log("Recording Length: " + playbackStorage.Duration);

                // Enable the ghost car
                ghostCar.gameObject.SetActive(true);

                // Clone identities - This allows the ghost car to be replayed as the player car
                ReplayObject.CloneReplayObjectIdentity(playerCar, ghostCar);

                // Start replaying
                playbackHandle = ReplayManager.BeginPlayback(playbackStorage, playbackScene);

                // Add end playback listener
                ReplayManager.AddPlaybackEndListener(playbackHandle, OnGhostVehiclePlaybackComplete);
            }

            // Start recording
            recordHandle = ReplayManager.BeginRecording(recordStorage, recordScene);
        }
        public IEnumerator StartAlternative()
        {
            // Create a replay scene from the active Unity scene
            ReplayScene recordScene = ReplayScene.FromCurrentScene();

            // Start recording
            ReplayHandle recordHandle = ReplayManager.BeginRecording(null, recordScene);

            // Wait for some time to pass
            yield return(new WaitForSeconds(1f));

            // Spawn a dynamic replay object
            ReplayObject obj = Instantiate(instanitatePrefab);

            // Add the object to the record scene only - This is a required step otherwise the object will not be recorded
            recordScene.AddReplayObject(obj);

            // Wait for some time to pass now that the object has been spawned
            yield return(new WaitForSeconds(1));

            // End recording
            // The resulting replay will have 1 second of nothing and then the dynamic object will be re-instantiated by the replay system
            ReplayManager.StopRecording(ref recordHandle);
        }
Пример #12
0
        private void DisplayPrefabErrors()
        {
            // Get the manager
            ReplayManager manager = target as ReplayManager;

            // Get the list of game objects
            GameObject[] prefabs = manager.prefabs;

            List <GameObject> replayErrors = new List <GameObject>();
            List <GameObject> prefabErrors = new List <GameObject>();

            foreach (GameObject go in prefabs)
            {
                // Check for null (Are allowed)
                if (go == null)
                {
                    continue;
                }

                // Try to get component
                ReplayObject obj = go.GetComponent <ReplayObject>();

                // Check for error
                if (obj == null)
                {
                    // Mark an error
                    replayErrors.Add(go);
                    continue;
                }

                // Check for prefab
                if (obj.IsPrefab == false)
                {
                    // Mark a prefab error
                    prefabErrors.Add(go);
                }
            }

            // Display a help box
            if (replayErrors.Count > 0)
            {
                StringBuilder builder = new StringBuilder();

                for (int i = 0; i < replayErrors.Count; i++)
                {
                    // Use the name in the error
                    builder.Append(replayErrors[i].name);

                    // There are more errors left
                    if (i < replayErrors.Count - 1)
                    {
                        builder.Append(", ");
                    }
                }

                // Display a help box
                EditorGUILayout.HelpBox(string.Format("The following prefabs do not have ReplayObject scripts attached and will be ignored at runtime: {0}", builder.ToString()), MessageType.Error);
            }

            // Display a help box
            if (prefabErrors.Count > 0)
            {
                StringBuilder builder = new StringBuilder();

                for (int i = 0; i < prefabErrors.Count; i++)
                {
                    // Use the name in the error
                    builder.Append(prefabErrors[i].name);

                    // There are more errors left
                    if (i < prefabErrors.Count - 1)
                    {
                        builder.Append(", ");
                    }
                }

                // Display a help box
                EditorGUILayout.HelpBox(string.Format("The following replay prefabs are not prefab assets and will be ignored at runtime: {0}. Make sure scene prefab instances are not registered", builder.ToString()), MessageType.Error);
            }
        }
Пример #13
0
        /// <summary>
        /// Attempts to restore any replay objects that were spawned or despawned during this snapshot.
        /// </summary>
        public void RestoreReplayObjects(ReplayScene scene, ReplayInitialDataBuffer initialStateBuffer)
        {
            // Get all active scene objects
            List <ReplayObject> activeReplayObjects = scene.ActiveReplayObjects;

            // Find all active replay objects
            foreach (ReplayObject obj in activeReplayObjects)
            {
                // Check if the object is no longer in the scene
                if (states.ContainsKey(obj.ReplayIdentity) == false)
                {
                    // Check for a prefab
                    if (obj.IsPrefab == false)
                    {
                        continue;
                    }

                    // We need to destroy the replay object
                    sharedDestroyQueue.Enqueue(obj);
                }
            }

            // Destroy all waiting objects
            while (sharedDestroyQueue.Count > 0)
            {
                ReplayManager.ReplayDestroy(sharedDestroyQueue.Dequeue().gameObject);
            }

            // Process all snapshot state data to check if we need to add any scene objects
            foreach (KeyValuePair <ReplayIdentity, ReplayState> replayObject in states)
            {
                bool found = false;

                // Check if the desiered object is active in the scene
                foreach (ReplayObject obj in activeReplayObjects)
                {
                    // Check for matching identity
                    if (obj.ReplayIdentity == replayObject.Key)
                    {
                        // The object is in the scene - do nothing
                        found = true;
                        break;
                    }
                }

                // We need to spawn the object
                if (found == false)
                {
                    // Get the replay state for the object because it contains the prefab information we need
                    ReplayState state = replayObject.Value;

                    // Reset the state for reading
                    state.PrepareForRead();

                    // Read the name of the prefab that we need to spawn
                    string name = state.ReadString();

                    // Try to find the matching prefab in our replay manager
                    GameObject prefab = ReplayManager.FindReplayPrefab(name);

                    // Check if the prefab was found
                    if (prefab == null)
                    {
                        // Check for no prefab name
                        if (string.IsNullOrEmpty(name) == true)
                        {
                            // Name information is unknown
                            name = "Unkwnown Replay Object (" + replayObject.Key + ")";

                            // Display scene object warning
                            Debug.LogWarning(string.Format("Failed to recreate replay scene object '{0}'. The object could not be found within the current scene and it is not a registered replay prefab. You may need to reload the scene before playback to ensure that all recorded objects are present.", name));
                        }
                        else
                        {
                            // Display prefab object warning
                            Debug.LogWarning(string.Format("Failed to recreate replay prefab '{0}'. No such prefab is registered.", name));
                        }
                        continue;
                    }

                    // Restore initial data
                    ReplayInitialData initialData = new ReplayInitialData();

                    // Check for valid state buffer
                    if (initialStateBuffer != null && initialStateBuffer.HasInitialReplayObjectData(replayObject.Key) == true)
                    {
                        // Restore the objects state data
                        initialData = initialStateBuffer.RestoreInitialReplayObjectData(replayObject.Key, timeStamp);//  RestoreInitialReplayObjectData(replayObject.Key);
                    }

                    Vector3    position = Vector3.zero;
                    Quaternion rotation = Quaternion.identity;
                    Vector3    scale    = Vector3.one;

                    // Update transform values
                    if ((initialData.InitialFlags & ReplayInitialDataFlags.Position) != 0)
                    {
                        position = initialData.position;
                    }
                    if ((initialData.InitialFlags & ReplayInitialDataFlags.Rotation) != 0)
                    {
                        rotation = initialData.rotation;
                    }
                    if ((initialData.InitialFlags & ReplayInitialDataFlags.Scale) != 0)
                    {
                        scale = initialData.scale;
                    }

                    // Call the instantiate method
                    GameObject result = ReplayManager.ReplayInstantiate(prefab, position, rotation);

                    if (result == null)
                    {
                        Debug.LogWarning(string.Format("Replay instanitate failed for prefab '{0}'. Some replay objects may be missing", name));
                        continue;
                    }

                    // Be sure to apply initial scale also
                    result.transform.localScale = scale;

                    // try to find the replay object script
                    ReplayObject obj = result.GetComponent <ReplayObject>();

                    // Check if we have the component
                    if (obj != null)
                    {
                        // Give the replay object its serialized identity so that we can send replay data to it
                        obj.ReplayIdentity = replayObject.Key;

                        // Map observed component identities
                        if (initialData.observedComponentIdentities != null)
                        {
                            int index = 0;

                            foreach (ReplayBehaviour behaviour in obj.ObservedComponents)
                            {
                                if (initialData.observedComponentIdentities.Length > index)
                                {
                                    behaviour.Identity = initialData.observedComponentIdentities[index];
                                }
                                index++;
                            }
                        }

                        // Register the created object
                        newReplayObjectsThisFrame.Add(new ReplayCreatedObject
                        {
                            replayObject      = obj,
                            replayInitialData = initialData,
                        });

                        // Trigger spawned event
                        ReplayBehaviour.Events.CallReplaySpawnedEvents(obj, position, rotation);
                    }
                }
            }


            // Re-parent replay objects
            foreach (ReplayCreatedObject created in newReplayObjectsThisFrame)
            {
                // Check for a parent identity
                if (created.replayInitialData.parentIdentity != null)
                {
                    bool foundTargetParent = false;

                    // We need to find the references parent
                    foreach (ReplayObject obj in scene.ActiveReplayObjects)
                    {
                        if (obj.ReplayIdentity == created.replayInitialData.parentIdentity)
                        {
                            // Parent the objects
                            created.replayObject.transform.SetParent(obj.transform, false);

                            // Set the flag
                            foundTargetParent = true;
                            break;
                        }
                    }

                    // Check if we failed to find the parent object
                    if (foundTargetParent == false)
                    {
                        // The target parent object is missing
                        Debug.LogWarning(string.Format("Newly created replay object '{0}' references identity '{1}' as a transform parent but the object could not be found in the current scene. Has the target parent been deleted this frame?", created.replayObject.name, created.replayInitialData.parentIdentity));
                    }
                }
            }

            // Clear ll tracked replay objects this frame
            newReplayObjectsThisFrame.Clear();
        }