private void RestoreMode(string serializedMode)
    {
        // Parse JSON back to objects
        var modeParams = JsonUtility.FromJson <ModeParameters>(serializedMode);
        // Build list that contains Components (only necessary information)
        var trackableComponentsList = modeParams.Parameters.Select(i => i.ComponentName);
        // Build list of gameObject's components that present in prev list
        var trackableComponents = gameObject.GetComponents(typeof(UnityEngine.Component)).Where(c => trackableComponentsList.Contains(c.GetType().ToString()));

        // Go through particular gameObject's components only
        foreach (var component in trackableComponents)
        {
            // Get type of component
            Type type = component.GetType();

            // Go through each field in this component
            foreach (var f in type.GetFields().Where(i => i.IsPublic))
            {
                // Find if there is a record for this field in ModeParameters
                var prm = modeParams.Parameters.FirstOrDefault(i => i.ComponentName == type.ToString() && i.ParamName == f.Name);
                // If record was found
                if (prm != default(Parameter))
                {
                    // If this is simple type then restore value
                    if (prm.ParamType != "CachedUnityObject")
                    {
                        object obj       = null;
                        var    converter = TypeDescriptor.GetConverter(f.FieldType);

                        if (!converter.CanConvertFrom(typeof(String)))
                        {
                            if (f.FieldType == typeof(Vector3))
                            {
                                obj = UnityTypesConverter.Vector3FromString(prm.Value);
                            }
                            if (f.FieldType == typeof(Quaternion))
                            {
                                obj = UnityTypesConverter.QuaternionFromString(prm.Value);
                            }
                        }
                        else
                        {
                            obj = converter.ConvertFromString(prm.Value);
                        }
                        f.SetValue(component, obj);
                    }
                    // Othervise take object from cache
                    else
                    {
                        var cachedObj = this.cachedUnityObjects.FirstOrDefault(i => i.Key == prm.Value && i.ModeGUID == modeParams.GUID);

                        if (cachedObj != default(CachedParameter))
                        {
                            f.SetValue(component, cachedObj.Value);
                        }
                    }
                }
            }

            // Go through each property in this component
            BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
            foreach (var p in type.GetProperties(flags))
            {
                // Find if there is a record for this field in ModeParameters
                var prm = modeParams.Parameters.FirstOrDefault(i => i.ComponentName == type.ToString() && i.ParamName == p.Name);
                // If record was found
                if (prm != default(Parameter))
                {
                    // If this is simple type then restore value
                    if (prm.ParamType != "CachedUnityObject")
                    {
                        object obj       = null;
                        var    converter = TypeDescriptor.GetConverter(p.PropertyType);

                        if (!converter.CanConvertFrom(typeof(String)))
                        {
                            if (p.PropertyType == typeof(Vector3))
                            {
                                obj = UnityTypesConverter.Vector3FromString(prm.Value);
                            }
                            if (p.PropertyType == typeof(Quaternion))
                            {
                                obj = UnityTypesConverter.QuaternionFromString(prm.Value);
                            }
                        }
                        else
                        {
                            obj = converter.ConvertFromString(prm.Value);
                        }

                        p.SetValue(component, obj, null);
                    }
                    // Othervise take object from cache
                    else
                    {
                        var cachedObj = this.cachedUnityObjects.FirstOrDefault(i => i.Key == prm.Value && i.ModeGUID == modeParams.GUID);

                        if (cachedObj != default(CachedParameter))
                        {
                            p.SetValue(component, cachedObj.Value, null);
                        }
                    }
                }
            }
        }
    }