/// <summary>
        /// Gets the state of the object and records it into the given sample.
        /// Returns the number of bytes that were recorded.
        /// </summary>
        /// <param name="o"></param>
        private int RecordState(object o, byte[][] sample)
        {
            RecordableMetadata meta = GetMetadata(o);
            StateDefinition    def;

            definitions.TryGetValue(o.GetType(), out def);
            sample[meta.id] = def.GetState(o);
            return(sample[meta.id].Length);
        }
        /// <summary>
        /// Sets the state of an object to the state it had in the given sample index.
        /// If there was no recording data for the given sample, or the sample index is
        /// out of range, the state will not be set.
        /// Returns true if the state was set.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="sampleIdx"></param>
        private bool SetState(object o, int sampleIdx)
        {
            RecordableMetadata meta = GetMetadata(o);
            StateDefinition    def  = GetDefinition(o.GetType());

            byte[][] sample = samples[sampleIdx];

            if (meta.id < sample.Length)
            {
                def.SetState(o, sample[meta.id]);
                return(true);
            }
            return(false);
        }
        /// <summary>
        /// Updates the state of the object, if it needs it.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="meta"></param>
        private void UpdateState(object o)
        {
            RecordableMetadata meta = GetMetadata(o);

            switch (meta.state)
            {
            case TimeState.NOMINAL:
            case TimeState.SLOW:
            case TimeState.FAST_FORWARD:
            case TimeState.PAUSE:
                meta.jumpFrameIdx++;
                break;

            case TimeState.REWIND:
                SetState(o, meta.jumpFrameIdx);
                //Debug.Log("Set state of " + o + " to frame " + meta.jumpFrameIdx);
                meta.jumpFrameIdx--;
                if (meta.jumpFrameIdx < 0)
                {
                    meta.jumpFrameIdx = 0;
                }
                break;

            case TimeState.PLAYBACK:
                // Set the state, advance the jump frame
                SetState(o, meta.jumpFrameIdx);
                meta.jumpFrameIdx++;
                // ensure the frame index never goes out of range.
                // once this happens, the state is set to nominal
                if (meta.jumpFrameIdx >= samples.Count)
                {
                    SetTimeState(o, TimeState.NOMINAL);
                }
                break;

            default:
                throw new InvalidProgramException("Invalid time flow state: " + meta.state);
            }
        }