Example #1
0
        public void OnReplayDeserialize(ReplayState state)
        {
            int size = state.Read32();

            for (int i = 0; i < size; i++)
            {
                // Read the target identity
                ReplayIdentity identity  = state.ReadIdentity();
                int            localSize = state.Read32();

                // Read all states
                for (int j = 0; j < localSize; j++)
                {
                    // Create empty data container
                    ReplayInitialData data = new ReplayInitialData();

                    // Deserialize data
                    data.OnReplayDeserialize(state);

                    // Register state
                    if (initialStates.ContainsKey(identity) == false)
                    {
                        initialStates.Add(identity, new List <ReplayInitialData>());
                    }

                    initialStates[identity].Add(data);
                }
            }
        }
Example #2
0
        public ReplayInitialData RestoreInitialReplayObjectData(ReplayIdentity identity, float timestamp)
        {
            // Create an error return value
            ReplayInitialData data = new ReplayInitialData
            {
                objectIdentity = identity,
                timestamp      = timestamp,
                position       = Vector3.zero,
                rotation       = Quaternion.identity,
                scale          = Vector3.one,
                parentIdentity = null,
                observedComponentIdentities = null,
            };

            // Check for existing object identity
            if (initialStates.ContainsKey(identity) == true)
            {
                // Get the state data
                List <ReplayInitialData> states = initialStates[identity];

                // Check for any states
                if (states.Count > 0)
                {
                    // Check for trivial case
                    if (states.Count == 1)
                    {
                        return(states[0]);
                    }

                    int   index = -1;
                    float smallestDifference = float.MaxValue;

                    // Find the best matching time stamp
                    for (int i = 0; i < states.Count; i++)
                    {
                        // Get timestamp difference
                        float timeDifference = Mathf.Abs(timestamp - states[i].timestamp);

                        // Check for smaller difference
                        if (timeDifference < smallestDifference)
                        {
                            // We have a new smallest time difference so make that the new target to beat
                            index = i;
                            smallestDifference = timeDifference;
                        }
                    }

                    // Check for valid index
                    if (index != -1)
                    {
                        // Use the state data at the best index match
                        data = states[index];
                    }
                }
            }
            return(data);
        }
Example #3
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);
        }
Example #4
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();
        }