/// <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(); }