帮我分析下这个脚本 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

namespace JNGame.SectorEditor
{

    [Serializable]
    public class SerializedRange : IEquatable<SerializedRange>
    {
        public float value;
        public Vector2 range;
        public bool Equals(SerializedRange other)
        {
            if (other == null) return false;
            return other.value.Equals(value) && other.range == range;
        }
    }

    [Serializable]
    public class SerializedTexture : IEquatable<SerializedTexture>
    {
        public string guid;
        public Vector2 tilling;
        public Vector2 offset;
        public bool Equals(SerializedTexture other)
        {
            if (other == null) return false;
            return guid == other.guid 
                   && tilling.Equals(other.tilling) 
                   && offset.Equals(other.offset);
        }
    }
    [Serializable]
    public class SerializedMaterialData
    {
        public string shaderName = String.Empty;
        // public bool enableInstancing;
        // public int renderQueue;
        // public bool doubleSidedGI;
        // public MaterialGlobalIlluminationFlags globalIlluminationFlags;
        // public MaterialVertexSkinningFlag vertexSkinningFlag;
        
        public SerializableDictionary<string, bool> shaderKeywords = new SerializableDictionary<string, bool>();
        
        public SerializableDictionary<string, int> intParamValues = new SerializableDictionary<string, int>();
        public SerializableDictionary<string, float> floatParamValues = new SerializableDictionary<string, float>();
        public SerializableDictionary<string, SerializedRange> rangeParamValues = new SerializableDictionary<string, SerializedRange>();//float+range
        public SerializableDictionary<string, Vector4> vectorParamValues = new SerializableDictionary<string, Vector4>();
        public SerializableDictionary<string, Color> colorParamValues = new SerializableDictionary<string, Color>();
        public SerializableDictionary<string, SerializedTexture> textureParamValues = new SerializableDictionary<string, SerializedTexture>();//名字+贴图的GUID
        public void Clear()
        {
            shaderKeywords.Clear();
            intParamValues.Clear();
            floatParamValues.Clear();
            rangeParamValues.Clear();
            vectorParamValues.Clear();
            colorParamValues.Clear();
            textureParamValues.Clear();
        }
    }
    
    [Serializable]
    public class SerializedMaterial
    {
        public SerializedMaterialData serializedData;
        public string json;

        public SerializedMaterial()
        {
            serializedData = new SerializedMaterialData();
        }

        private void ApplyToMaterialWithoutTex(Material material, HashSet<string> lockedPropertyNames)
        {
            // material.enableInstancing = serializedData.enableInstancing;
            // material.renderQueue = serializedData.renderQueue;
            // material.doubleSidedGI = serializedData.doubleSidedGI;
            // material.globalIlluminationFlags = serializedData.globalIlluminationFlags;
            // material.VertexSkinningFlag = serializedData.vertexSkinningFlag;
            
            foreach (var kv in serializedData.intParamValues)
            {
                var paramName = kv.Key;
                var value = kv.Value;
                if (material.HasInt(paramName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(paramName)))
                {
                    material.SetInt(paramName, value);
                }
            }
            foreach (var kv in serializedData.floatParamValues)
            {
                var paramName = kv.Key;
                var value = kv.Value;
                if (material.HasFloat(paramName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(paramName)))
                {
                    material.SetFloat(paramName, value);   
                }
            }
            foreach (var kv in serializedData.rangeParamValues)
            {
                var paramName = kv.Key;
                var value = kv.Value.value;
                if (material.HasFloat(paramName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(paramName)))
                {
                    material.SetFloat(paramName, value);   
                }
            }
            foreach (var kv in serializedData.vectorParamValues)
            {
                var paramName = kv.Key;
                var value = kv.Value;
                if (material.HasVector(paramName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(paramName)))
                {
                    material.SetVector(paramName, value);   
                }
            }
            foreach (var kv in serializedData.colorParamValues)
            {
                var paramName = kv.Key;
                var value = kv.Value;
                if (material.HasColor(paramName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(paramName)))
                {
                    material.SetColor(paramName, value);   
                }
            }
        }
        
        //把材质参数赋值给材质，贴图数据从外部传入（主要用于处理运行时）
        public bool ApplyToMaterialWithTextures(Material material, HashSet<string> lockedPropertyNames, string[] texturePropertyNames, Texture[] textures)
        {
            serializedData = JsonUtility.FromJson<SerializedMaterialData>(json);
            if (serializedData == null) return false;
            ApplyToMaterialWithoutTex(material, lockedPropertyNames);
            for (int i = 0; i < texturePropertyNames.Length; i++)
            {
                var propertyName = texturePropertyNames[i];
                if (serializedData.textureParamValues.TryGetValue(propertyName, out var serializedTexture))
                {
                    if (material.HasTexture(propertyName) && (lockedPropertyNames == null || !lockedPropertyNames.Contains(propertyName)))
                    {
                        material.SetTexture(propertyName, textures[i]);
                        material.SetTextureOffset(propertyName, serializedTexture.offset);
                        material.SetTextureScale(propertyName, serializedTexture.tilling);   
                    }   
                }
            }
            if (serializedData.shaderKeywords != null)
            {
                material.shaderKeywords = serializedData.shaderKeywords.Keys.ToArray();
                foreach (var kv in serializedData.shaderKeywords)
                {
                    var keywordName = kv.Key;
                    var value = kv.Value;
                    if (value)
                    {
                        material.EnableKeyword(keywordName);
                    }
                    else
                    {
                        material.DisableKeyword(keywordName);
                    }
                }
            }
            return true;
        }
#if UNITY_EDITOR
        public SerializedMaterial(Material material)
        {
            StoreMaterial(material);
        }        
        
        //把材质参数序列化下来
        public void StoreMaterial(Material material)
        {
            if (serializedData == null)
            {
                serializedData = new SerializedMaterialData();   
            }

            serializedData.Clear();
            serializedData.shaderName = material.shader.name;
            
            // serializedData.enableInstancing = material.enableInstancing;
            // serializedData.renderQueue = material.renderQueue;
            // serializedData.doubleSidedGI = material.doubleSidedGI;
            // serializedData.globalIlluminationFlags = material.globalIlluminationFlags;
            // serializedData.vertexSkinningFlag = material.VertexSkinningFlag;
            foreach (var keyword in material.shaderKeywords)
            {
                serializedData.shaderKeywords.Add(keyword, material.IsKeywordEnabled(keyword));
            }
            
            int count = material.shader.GetPropertyCount();
            for (int i = 0; i < count; i++)
            {
                var propertyName = material.shader.GetPropertyName(i);
                var propertyType = material.shader.GetPropertyType(i);
                switch (propertyType) {
                    case ShaderPropertyType.Int:
                        serializedData.intParamValues.Add(propertyName, material.GetInt(propertyName));
                        break;
                    case ShaderPropertyType.Float:
                        serializedData.floatParamValues.Add(propertyName, material.GetFloat(propertyName));
                        break;
                    case ShaderPropertyType.Range:
                        var value = material.GetFloat(propertyName);
                        var range = material.shader.GetPropertyRangeLimits(i);
                        var serializedRange = new SerializedRange()
                        {
                            value = value,
                            range = range
                        };
                        serializedData.rangeParamValues.Add(propertyName, serializedRange);
                        break;
                    case ShaderPropertyType.Vector:
                        serializedData.vectorParamValues.Add(propertyName, material.GetVector(propertyName));
                        break;
                    case ShaderPropertyType.Color:
                        serializedData.colorParamValues.Add(propertyName, material.GetColor(propertyName));
                        break;
                    case ShaderPropertyType.Texture:
                        var texture = material.GetTexture(propertyName);
                        var path = AssetDatabase.GetAssetPath(texture);
                        var guid = AssetDatabase.AssetPathToGUID(path);
                        var tilling = material.GetTextureScale(propertyName);
                        var offset = material.GetTextureOffset(propertyName);
                        serializedData.textureParamValues.Add(propertyName, new SerializedTexture()
                        {
                            guid = guid,
                            tilling = tilling,
                            offset = offset,
                        });
                        break;
                }
            }
            json = JsonUtility.ToJson(serializedData);
        }
        
        public bool Equals(Material material)
        {
            if (!material) return false;
            if (serializedData == null) return false;
            //是否shader一致
            if (material.shader.name != serializedData.shaderName) return false;
            //一些其他参数是否一致
            // if (material.enableInstancing != serializedData.enableInstancing) return false;
            // if (material.renderQueue != serializedData.renderQueue) return false;
            // if (material.doubleSidedGI != serializedData.doubleSidedGI) return false;
            // if (material.globalIlluminationFlags != serializedData.globalIlluminationFlags) return false;
            // if (material.VertexSkinningFlag != serializedData.vertexSkinningFlag) return false;
            //keyword是否一致
            foreach (var keyword in material.shaderKeywords)
            {
                if (!serializedData.shaderKeywords.ContainsKey(keyword)) return false;
                if (serializedData.shaderKeywords[keyword] != material.IsKeywordEnabled(keyword)) return false;
            }
            int count = material.shader.GetPropertyCount();
            //遍历材质参数
            for (int i = 0; i < count; i++)
            {
                string propertyName = material.shader.GetPropertyName(i);
                var propertyType = material.shader.GetPropertyType(i);
                // check param value
                switch (propertyType)
                {
                    case ShaderPropertyType.Int:
                        if (serializedData.intParamValues.TryGetValue(propertyName, out var intValue))
                        {
                            if (intValue != material.GetInt(propertyName)) return false;   
                        }
                        else
                        {
                            return false;
                        }
                        break;
                    case ShaderPropertyType.Float:
                        if (serializedData.floatParamValues.TryGetValue(propertyName, out var floatValue))
                        {
                            if (!floatValue.Equals(material.GetFloat(propertyName))) return false;   
                        }
                        else
                        {
                            return false;
                        }
                        break;
                    case ShaderPropertyType.Range:
                        if (serializedData.rangeParamValues.TryGetValue(propertyName, out var rangeValue))
                        {
                            if (!rangeValue.Equals(new SerializedRange()
                                {
                                    value = material.GetFloat(propertyName),
                                    range = material.shader.GetPropertyRangeLimits(i)
                                }))
                            {
                                return false;
                            }
                        }
                        else
                        {
                            return false;
                        }
                        break;
                    case ShaderPropertyType.Vector:
                        if (serializedData.vectorParamValues.TryGetValue(propertyName, out var vectorValue))
                        {
                            if (!vectorValue.Equals(material.GetVector(propertyName))) return false;   
                        }
                        else
                        {
                            return false;
                        }
                        break;
                    case ShaderPropertyType.Color:
                        if (serializedData.colorParamValues.TryGetValue(propertyName, out var colorValue))
                        {
                            if (!colorValue.Equals(material.GetColor(propertyName))) return false;   
                        }
                        else
                        {
                            return false;
                        }
                        break;
                    case ShaderPropertyType.Texture:
                        if (serializedData.textureParamValues.TryGetValue(propertyName, out var textureValue))
                        {
                            var materialTexture = material.GetTexture(propertyName);
                            var materialTexturePath = AssetDatabase.GetAssetPath(materialTexture);
                            var materialTextureGuid = AssetDatabase.AssetPathToGUID(materialTexturePath);
                            var isTexEqual = textureValue.Equals(new SerializedTexture()
                            {
                                guid = materialTextureGuid,
                                tilling = material.GetTextureScale(propertyName),
                                offset = material.GetTextureOffset(propertyName),
                            });
                            if (!isTexEqual) return false;
                        }
                        else
                        {
                            return false;
                        }
                        break;
                }
            }
            return true;
        }
        
        public bool ApplyToMaterial(Material material, HashSet<string> lockedPropertyNames)
        {
            if (material.shader.name != serializedData.shaderName) return false;
            ApplyToMaterialWithoutTex(material, lockedPropertyNames);
            foreach (var kv in serializedData.textureParamValues)
            {
                var paramName = kv.Key;
                if (lockedPropertyNames != null && lockedPropertyNames.Contains(paramName)) continue;
                var serializedTexture = kv.Value;
                var path = AssetDatabase.GUIDToAssetPath(serializedTexture.guid);
                var texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
                if (texture)
                {
                    material.SetTexture(paramName, texture);
                }
                material.SetTextureOffset(paramName, serializedTexture.offset);
                material.SetTextureScale(paramName, serializedTexture.tilling);
            }
            if (serializedData.shaderKeywords != null)
            {
                material.shaderKeywords = serializedData.shaderKeywords.Keys.ToArray();
                foreach (var kv in serializedData.shaderKeywords)
                {
                    var keywordName = kv.Key;
                    var value = kv.Value;
                    if (value)
                    {
                        material.EnableKeyword(keywordName);
                    }
                    else
                    {
                        material.DisableKeyword(keywordName);
                    }
                }
            }
            return true;
        }
        
        public List<(string, Texture)> LoadTextures()
        {
            var propertyNameTextures = new List<(string, Texture)>();
            foreach (var kv in serializedData.textureParamValues)
            {
                var propertyName = kv.Key;
                var serializedTexture = kv.Value;
                var path = AssetDatabase.GUIDToAssetPath(serializedTexture.guid);
                var texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
                if (texture)
                {
                    propertyNameTextures.Add((propertyName, texture));   
                }
            }
            return propertyNameTextures;
        }
#endif
    }
}