ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Unity资产文件浮点数修改为定点数工具记录

2022-03-02 12:03:00  阅读:173  来源: 互联网

标签:FP yaml 浮点数 Unity targetNode FindPropertyRelative 定点数 var Children



网络同步验证需要定点数,但是项目中大量资产文件使用了浮点数,需要工具来统一修改为定点数

  1. 通过将向浮点数添加特定的Attribute,并将类型替换成定点数类型,在OnPostprocessAllAssets时记录修改的cs文件GUID
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets,
        string[] movedFromAssetPaths) {
        _lastProcessedScriptTypes.Clear();
        _tsSerRecord = (TSSerScriptRecord)EditorGUIUtility.Load(TSSerRecordRelativePath);
        bool isDirty = false;
        foreach (string path in importedAssets) {
            Debug.Log("reimport Asset: " + path);
            if (Path.GetExtension(path) == ".cs") {
                string guid = AssetDatabase.AssetPathToGUID(path);
                var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
                if (monoScript != null) {
                    var type = monoScript.GetClass();
                    if (type != null) {
                        Debug.Log($"monoScript type: {type}");
                        if (type.IsSubclassOf(typeof(Object))) {
                            var tsFields =
                                (from field in type.GetFields(BindingFlags.Instance | BindingFlags.Static |
                                                              BindingFlags.Public | BindingFlags.NonPublic)
                                    where field.IsDefined(typeof(TSSerAttribute), false)
                                    select field).ToArray();
                            if (tsFields.Length <= 0) continue;
                            if (_tsSerRecord.changedScriptGuids.Contains(guid)) continue;
                            _tsSerRecord.changedScriptGuids.Add(guid);
                            isDirty = true;
                        }
                    }
                }
            }
        }

        if (isDirty) {
            EditorUtility.SetDirty(_tsSerRecord);
            AssetDatabase.Refresh();
        }
    }
  1. 通过FR2查找引用插件,查找到所有引用此脚本的资产文件
  2. 读取查找到的资产文件的yaml(通过YamlDotNet),遍历所有的Document,通过对比yaml的m_Script中的GUID确定yaml中信息位置
  3. 通过yaml可以得到修改前的旧值通过SerializedObject查找SerializedProperty设置转换后的定点值,最后应用修改ApplyModifiedProperties
static void ProcessTsAttributeSO(List<FieldInfo> fieldList, string scriptGuid, ScriptableObject so)
{
    var path = AssetDatabase.GetAssetPath(so);
    path = Path.Combine(Application.dataPath.Replace("/Assets", ""), path);
    var yaml = LoadYamlStream(path);
    if (yaml == null)
    {
        Debug.LogError($"LoadYamlStream Error {path}");
        return;
    }
    for (int i = 0; i < yaml.Documents.Count; i++)
    {
        var mapping = (YamlMappingNode)yaml.Documents[i].RootNode;
        foreach (var entry in mapping.Children)
        {
            if (entry.Key.ToString().Contains("MonoBehaviour"))
            {
                if (entry.Value is YamlMappingNode monoMapping)
                {
                    string guid =
                        ((monoMapping.Children["m_Script"] as YamlMappingNode)?.Children["guid"] as
                            YamlScalarNode)?.Value;
                    if (guid == scriptGuid)
                    {
                        var serObj = new SerializedObject(so);
                        bool isDirty = false;
                        foreach (var field in fieldList)
                        {
                            var uncovertNode = monoMapping.Children[field.Name];
                            isDirty = SingleValueConvertTsValue(serObj, field, uncovertNode);
                        }

                        if (isDirty)
                        {
                            serObj.ApplyModifiedProperties();
                            EditorUtility.SetDirty(so);
                        }
                    }
                }
            }
        }
    }
}
    static bool SingleValueConvertTsValue(SerializedObject serObj, FieldInfo fi, YamlNode uncovertNode)
    {
        var fieldType = fi.FieldType;

        #region FP
        if (fieldType == typeof(FP))
        {
            var targetNode = uncovertNode as YamlScalarNode;
            if (targetNode != null)
            {
                if (float.TryParse(targetNode.Value,
    out var oldValue))
                {
                    serObj.FindProperty(fi.Name)
                            .FindPropertyRelative("_serializedValue")
                            .longValue =
                        ((FP)oldValue).RawValue;
                    return true;
                }
            }
        }

        #endregion FP end

        #region TSVector2
        if (fieldType == typeof(TSVector2))
        {
            var targetNode = uncovertNode as YamlMappingNode;
            if(targetNode != null)
            {
                bool boolX, boolY;
                var strX = (targetNode.Children["x"] as YamlScalarNode)?.Value;
                var strY = (targetNode.Children["y"] as YamlScalarNode)?.Value;
                if(boolX = float.TryParse(strX, out var oldFloatX))
                {
                    serObj.FindProperty(fi.Name)
                        .FindPropertyRelative("x")
                        .FindPropertyRelative("_serializedValue").longValue = ((FP)oldFloatX).RawValue;
                }

                if (boolY = float.TryParse(strY, out var oldFloatY))
                {
                    serObj.FindProperty(fi.Name)
                        .FindPropertyRelative("y")
                        .FindPropertyRelative("_serializedValue").longValue = ((FP)oldFloatY).RawValue;
                }
                return boolX && boolY;
            }
        }
        #endregion TSVector2 end

        #region TSVector
        if (fieldType == typeof(TSVector))
        {
            var targetNode = uncovertNode as YamlMappingNode;
            if (targetNode != null)
            {
                bool boolX, boolY, boolZ;
                var strX = (targetNode.Children["x"] as YamlScalarNode)?.Value;
                var strY = (targetNode.Children["y"] as YamlScalarNode)?.Value;
                var strZ = (targetNode.Children["z"] as YamlScalarNode)?.Value;
                if (boolX = float.TryParse(strX, out var oldFloatX))
                {
                    serObj.FindProperty(fi.Name)
                        .FindPropertyRelative("x")
                        .FindPropertyRelative("_serializedValue").longValue = ((FP)oldFloatX).RawValue;
                }

                if (boolY = float.TryParse(strY, out var oldFloatY))
                {
                    serObj.FindProperty(fi.Name)
                        .FindPropertyRelative("y")
                        .FindPropertyRelative("_serializedValue").longValue = ((FP)oldFloatY).RawValue;
                }

                if (boolZ = float.TryParse(strZ, out var oldFloatZ))
                {
                    serObj.FindProperty(fi.Name)
                        .FindPropertyRelative("z")
                        .FindPropertyRelative("_serializedValue").longValue = ((FP)oldFloatZ).RawValue;
                }
                return boolX && boolY && boolZ;
            }
        }

        #endregion TSVector2 end

        #region Curve

        if (fieldType == typeof(Curve))
        {
            var targetNode = uncovertNode as YamlMappingNode;
            if (targetNode != null)
            {
                // 空曲线可能会出现空情况
                if (targetNode.Children.ContainsKey("m_Curve"))
                {
                    var curveSeqNode = targetNode.Children["m_Curve"] as YamlSequenceNode;
                    if (curveSeqNode != null)
                    {
                        var curvekeyListSerProperty = serObj.FindProperty(fi.Name)
                            .FindPropertyRelative("keys")
                            .FindPropertyRelative("innerlist");
                        curvekeyListSerProperty.ClearArray();
                        bool errorState = true;
                        for (int i = 0; i < curveSeqNode.Children.Count; i++)
                        {
                            var mapNode = curveSeqNode.Children[i] as YamlMappingNode;
                            if (mapNode != null)
                            {
                                bool boolTime, boolValue, boolInTangent, boolOutTangent;

                                var strTime = (mapNode.Children["time"] as YamlScalarNode)?.Value;
                                var strValue = (mapNode.Children["value"] as YamlScalarNode)?.Value;
                                var strInTangent = (mapNode.Children["inSlope"] as YamlScalarNode)?.Value;
                                var strOutTangent = (mapNode.Children["outSlope"] as YamlScalarNode)?.Value;
								
								这个是通过SerializedProperty修改List类型
                                curvekeyListSerProperty.InsertArrayElementAtIndex(i);
                                var insertElement = curvekeyListSerProperty.GetArrayElementAtIndex(i);

                                if (boolTime = float.TryParse(strTime, out var floatTime))
                                {
                                    insertElement
                                        .FindPropertyRelative("position")
                                        .FindPropertyRelative("_serializedValue")
                                        .longValue = ((FP)floatTime).RawValue;
                                }
                                if (boolValue = float.TryParse(strValue, out var floatValue))
                                {
                                    insertElement
                                        .FindPropertyRelative("value")
                                        .FindPropertyRelative("_serializedValue")
                                        .longValue = ((FP)floatValue).RawValue;
                                }
                                if (boolInTangent = float.TryParse(strInTangent, out var floatInTangent))
                                {
                                    insertElement
                                        .FindPropertyRelative("tangentIn")
                                        .FindPropertyRelative("_serializedValue")
                                        .longValue = ((FP)floatInTangent).RawValue;
                                }
                                if (boolOutTangent = float.TryParse(strOutTangent, out var floatOutTangent))
                                {
                                    insertElement
                                        .FindPropertyRelative("tangentOut")
                                        .FindPropertyRelative("_serializedValue")
                                        .longValue = ((FP)floatOutTangent).RawValue;
                                }

                                errorState = errorState && boolTime && boolValue && boolInTangent && boolOutTangent;
                            }
                        }
                        return errorState;
                    }
                }
            }
        }


注意 当在MonoBehaviour类型cs脚本中修改值时,资产文件yaml其实是不变的,但是如果你这时候修改Inspector,yaml将会被刷新成新信息,你就无法获得以前的旧值了,上面的核心思路就是找到引用资产文件,通过yaml获得旧值,通过SerializedObject设置新值和刷新yaml


标签:FP,yaml,浮点数,Unity,targetNode,FindPropertyRelative,定点数,var,Children
来源: https://blog.csdn.net/weixin_45029839/article/details/123226466

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有