Пример #1
0
        public static bool FixGameObjectIssue(GameObjectIssueRecord issue, GameObject go, Component component, RecordType type)
        {
            bool result = false;

            if (type == RecordType.MissingComponent)
            {
                bool hasIssue = GameObjectHasMissingComponent(go);

                if (hasIssue)
                {
                    FixMissingComponents(issue, go);
                    result = !GameObjectHasMissingComponent(go);
                }
                else
                {
                    Debug.LogWarning(Maintainer.LOG_PREFIX + "Looks like this issue was already fixed:\n" + issue);
                }
            }
            else if (type == RecordType.MissingReference)
            {
                result = FixMissingReference(issue, component);
            }

            return(result);
        }
Пример #2
0
        public static bool FixObjectIssue(GameObjectIssueRecord issue, Object obj, Component component, IssueKind type)
        {
            var result = false;

            if (type == IssueKind.MissingComponent)
            {
                var hasIssue = GameObjectHasMissingComponent(obj as GameObject);

                if (hasIssue)
                {
                    FixMissingComponents(issue, obj as GameObject, false);
                    result = !GameObjectHasMissingComponent(obj as GameObject);
                }
                else
                {
                    result = true;
                }
            }
            else if (type == IssueKind.MissingReference)
            {
                if (component != null)
                {
                    result = FixMissingReference(component, issue.propertyPath, issue.Location);
                }
                else
                {
                    result = FixMissingReference(obj, issue.propertyPath, issue.Location);
                }
            }

            return(result);
        }
Пример #3
0
        public static FixResult FixObjectIssue(GameObjectIssueRecord issue, Object obj, Component component, IssueKind type)
        {
            FixResult result;

            if (type == IssueKind.MissingComponent)
            {
                var go       = (GameObject)obj;
                var hasIssue = GameObjectHasMissingComponent(go);

                if (hasIssue)
                {
                    if (PrefabUtility.IsPartOfPrefabAsset(go))
                    {
                        var allTransforms = go.transform.root.GetComponentsInChildren <Transform>(true);
                        foreach (var child in allTransforms)
                        {
                            FixMissingComponents(issue, child.gameObject, false);
                        }
                    }
                    else
                    {
                        FixMissingComponents(issue, go, false);
                    }

                    if (!GameObjectHasMissingComponent(go))
                    {
                        result = new FixResult(true);
                    }
                    else
                    {
                        result = FixResult.CreateError("Fix attempt failed!");
                    }
                }
                else
                {
                    result = new FixResult(true);
                }
            }
            else if (type == IssueKind.MissingReference)
            {
                result = FixMissingReference(component != null ? component : obj, issue.propertyPath, issue.Location);
            }
            else
            {
                result = FixResult.CreateError("IssueKind is not supported!");
            }

            return(result);
        }
Пример #4
0
        public static FixResult FixObjectIssue(GameObjectIssueRecord issue, Object obj, Component component, IssueKind type)
        {
            FixResult result;

            if (type == IssueKind.MissingComponent)
            {
                var hasIssue = GameObjectHasMissingComponent(obj as GameObject);

                if (hasIssue)
                {
                    FixMissingComponents(issue, obj as GameObject, false);
                    if (!GameObjectHasMissingComponent(obj as GameObject))
                    {
                        result = new FixResult(true);
                    }
                    else
                    {
                        result = FixResult.CreateError("Fix attempt failed!");
                    }
                }
                else
                {
                    result = new FixResult(true);
                }
            }
            else if (type == IssueKind.MissingReference)
            {
                if (component != null)
                {
                    result = FixMissingReference(component, issue.propertyPath, issue.Location);
                }
                else
                {
                    result = FixMissingReference(obj, issue.propertyPath, issue.Location);
                }
            }
            else
            {
                result = FixResult.CreateError("IssueKind is not supported!");
            }

            return(result);
        }
Пример #5
0
        // ----------------------------------------------------------------------------
        // fix missing component
        // ----------------------------------------------------------------------------

        private static void FixMissingComponents(GameObjectIssueRecord issue, GameObject go)
        {
            CSObjectTools.SelectGameObject(go, issue.location);

            ActiveEditorTracker tracker = CSEditorTools.GetActiveEditorTrackerForSelectedObject();

            tracker.RebuildIfNecessary();

            bool touched = false;

            Editor[] activeEditors = tracker.activeEditors;
            for (int i = activeEditors.Length - 1; i >= 0; i--)
            {
                Editor editor = activeEditors[i];
                if (CSObjectTools.GetLocalIdentifierInFileForObject(editor.serializedObject.targetObject) == issue.componentId)
                {
                    Object.DestroyImmediate(editor.target, true);
                    touched = true;
                }
            }

            if (touched)
            {
#if UNITY_5_0_PLUS
                if (issue.location == RecordLocation.Scene)
                {
                    CSSceneTools.MarkSceneDirty();
                }
                else
                {
                    EditorUtility.SetDirty(go);
                }
#else
                EditorUtility.SetDirty(go);
#endif
            }

            //CSObjectTools.SelectGameObject(null, issue.location);
        }
Пример #6
0
        // ----------------------------------------------------------------------------
        // fix missing reference
        // ----------------------------------------------------------------------------

        private static bool FixMissingReference(GameObjectIssueRecord issue, Component component)
        {
            SerializedObject   so = new SerializedObject(component);
            SerializedProperty sp = so.FindProperty(issue.propertyPath);

            if (sp.propertyType == SerializedPropertyType.ObjectReference)
            {
                if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0)
                {
                    sp.objectReferenceInstanceIDValue = 0;

#if UNITY_5_2_PLUS
                    // fixes dirty scene flag after batch issues fix
                    // due to the additional undo action
                    so.ApplyModifiedPropertiesWithoutUndo();
#else
                    so.ApplyModifiedProperties();
#endif

#if UNITY_5_0_PLUS
                    if (issue.location == RecordLocation.Scene)
                    {
                        CSSceneTools.MarkSceneDirty();
                    }
                    else
                    {
                        EditorUtility.SetDirty(component);
                    }
#else
                    EditorUtility.SetDirty(component);
#endif
                }
            }

            return(true);
        }
Пример #7
0
        // ----------------------------------------------------------------------------
        // fix missing component
        // ----------------------------------------------------------------------------

        private static bool FixMissingComponents(GameObjectIssueRecord issue, GameObject go, bool alternative)
        {
            var touched = false;

#if UNITY_2019_1_OR_NEWER
            var removedCount = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go);
            if (removedCount > 0)
            {
                touched = true;
            }
#else
            if (!alternative)
            {
                CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene);
            }

            var tracker = CSEditorTools.GetActiveEditorTrackerForSelectedObject();
            if (tracker == null)
            {
                Debug.LogError(Maintainer.ConstructError("Can't get active tracker."));
                return(false);
            }
            tracker.RebuildIfNecessary();

            var activeEditors = tracker.activeEditors;
            for (var i = activeEditors.Length - 1; i >= 0; i--)
            {
                var editor = activeEditors[i];
                if (editor.serializedObject.targetObject == null)
                {
                    Object.DestroyImmediate(editor.target, true);
                    touched = true;
                }
            }

            if (alternative)
            {
                return(touched);
            }

            if (!touched)
            {
                // missing script could be hidden with hide flags, so let's try select it directly and repeat
                var serializedObject = new SerializedObject(go);
                var componentsArray  = serializedObject.FindProperty("m_Component");
                if (componentsArray != null)
                {
                    for (var i = componentsArray.arraySize - 1; i >= 0; i--)
                    {
                        var componentPair   = componentsArray.GetArrayElementAtIndex(i);
                        var nestedComponent = componentPair.FindPropertyRelative("component");
                        if (nestedComponent != null)
                        {
                            if (MissingReferenceDetector.IsPropertyHasMissingReference(nestedComponent))
                            {
                                var instanceId = nestedComponent.objectReferenceInstanceIDValue;
                                if (instanceId == 0)
                                {
                                    var fileId = nestedComponent.FindPropertyRelative("m_FileID");
                                    if (fileId != null)
                                    {
                                        instanceId = fileId.intValue;
                                    }
                                }

                                Selection.instanceIDs = new [] { instanceId };
                                touched |= FixMissingComponents(issue, go, true);
                            }
                        }
                        else
                        {
                            Debug.LogError(Maintainer.LogPrefix + "Couldn't find component in component pair!");
                            break;
                        }
                    }

                    if (touched)
                    {
                        CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene);
                    }
                }
                else
                {
                    Debug.LogError(Maintainer.LogPrefix + "Couldn't find components array!");
                }
            }
#endif
            if (touched)
            {
                if (issue.Location == RecordLocation.Scene)
                {
                    CSSceneTools.MarkSceneDirty();
                }
                else
                {
                    EditorUtility.SetDirty(go);
                }
            }

            return(touched);
        }
Пример #8
0
        // -----------------------------------------------------------------------------
        // fix missing component
        // -----------------------------------------------------------------------------

        private static bool FixMissingComponents(GameObjectIssueRecord issue, GameObject go, bool alternative)
        {
            var touched = false;

            // TODO: re-check in Unity 2021
            // unfortunately RemoveMonoBehavioursWithMissingScript does not works correctly:
            // https://forum.unity.com/threads/remove-all-missing-components-in-prefabs.897761/
            // so it will be enabled back in later Unity versions

            /*var removedCount = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go);
             * if (removedCount > 0)
             * {
             *      touched = true;
             * }*/

            if (!alternative)
            {
                CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene);
            }

            var tracker = CSEditorTools.GetActiveEditorTrackerForSelectedObject();

            if (tracker == null)
            {
                Debug.LogError(Maintainer.ConstructError("Can't get active tracker."));
                return(false);
            }
            tracker.RebuildIfNecessary();

            var activeEditors = tracker.activeEditors;

            for (var i = activeEditors.Length - 1; i >= 0; i--)
            {
                var editor = activeEditors[i];
                if (editor.serializedObject.targetObject == null)
                {
                    Object.DestroyImmediate(editor.target, true);
                    touched = true;
                }
            }

            if (alternative)
            {
                return(touched);
            }

            if (!touched)
            {
                // missing script could be hidden with hide flags, so let's try select it directly and repeat
                var serializedObject = new SerializedObject(go);
                var componentsArray  = serializedObject.FindProperty("m_Component");
                if (componentsArray != null)
                {
                    for (var i = componentsArray.arraySize - 1; i >= 0; i--)
                    {
                        var componentPair   = componentsArray.GetArrayElementAtIndex(i);
                        var nestedComponent = componentPair.FindPropertyRelative("component");
                        if (nestedComponent != null)
                        {
                            if (MissingReferenceDetector.IsPropertyHasMissingReference(nestedComponent))
                            {
                                var instanceId = nestedComponent.objectReferenceInstanceIDValue;
                                if (instanceId == 0)
                                {
                                    var fileId = nestedComponent.FindPropertyRelative("m_FileID");
                                    if (fileId != null)
                                    {
                                        instanceId = fileId.intValue;
                                    }
                                }

                                Selection.instanceIDs = new [] { instanceId };
                                touched |= FixMissingComponents(issue, go, true);
                            }
                        }
                        else
                        {
                            Debug.LogError(Maintainer.LogPrefix + "Couldn't find component in component pair!");
                            break;
                        }
                    }

                    if (touched)
                    {
                        CSObjectTools.SelectGameObject(go, issue.Location == RecordLocation.Scene);
                    }
                }
                else
                {
                    Debug.LogError(Maintainer.LogPrefix + "Couldn't find components array!");
                }
            }

            if (touched)
            {
                if (issue.Location == RecordLocation.Scene)
                {
                    CSSceneTools.MarkSceneDirty();
                }
                else
                {
                    EditorUtility.SetDirty(go);
                }
            }

            return(touched);
        }
Пример #9
0
        private static void CheckObjectForIssues(List <IssueRecord> issues, string path, GameObject go, bool checkingScene)
        {
            RecordLocation location = checkingScene ? RecordLocation.Scene : RecordLocation.Prefab;

            // ----------------------------------------------------------------------------
            // looking for object-level issues
            // ----------------------------------------------------------------------------

            if (!MaintainerSettings.Issues.touchInactiveGameObjects)
            {
                if (checkingScene)
                {
                    if (!go.activeInHierarchy)
                    {
                        return;
                    }
                }
                else
                {
                    if (!go.activeSelf)
                    {
                        return;
                    }
                }
            }

            // ----------------------------------------------------------------------------
            // checking all components for ignores
            // ----------------------------------------------------------------------------

            bool checkForIgnores      = (MaintainerSettings.Issues.componentIgnores != null && MaintainerSettings.Issues.componentIgnores.Length > 0);
            bool skipEmptyMeshFilter  = false;
            bool skipEmptyAudioSource = false;

            Component[] allComponents      = go.GetComponents <Component>();
            int         allComponentsCount = allComponents.Length;

            List <Component> components           = new List <Component>(allComponentsCount);
            List <Type>      componentsTypes      = new List <Type>(allComponentsCount);
            List <string>    componentsNames      = new List <string>(allComponentsCount);
            List <string>    componentsFullNames  = new List <string>(allComponentsCount);
            List <string>    componentsNamespaces = new List <string>(allComponentsCount);

            int componentsCount = 0;

            for (int i = 0; i < allComponentsCount; i++)
            {
                Component component = allComponents[i];

                if (component == null)
                {
                    if (MaintainerSettings.Issues.missingComponents)
                    {
                        issues.Add(GameObjectIssueRecord.Create(RecordType.MissingComponent, location, path, go));
                    }
                    continue;
                }

                Type   componentType      = component.GetType();
                string componentName      = componentType.Name;
                string componentFullName  = componentType.FullName;
                string componentNamespace = componentType.Namespace;

                /*
                 * checking object for the components which may affect
                 * other components and produce false positives
                 */

                // allowing empty mesh filters for the objects with attached TextMeshPro and 2D Toolkit components.
                if (!skipEmptyMeshFilter)
                {
                    skipEmptyMeshFilter = (componentFullName == "TMPro.TextMeshPro") || componentName.StartsWith("tk2d");
                }

                // allowing empty AudioSources for the objects with attached standard FirstPersonController.
                if (!skipEmptyAudioSource)
                {
                    skipEmptyAudioSource = componentFullName == "UnityStandardAssets.Characters.FirstPerson.FirstPersonController";
                }

                // skipping disabled components
                if (!MaintainerSettings.Issues.touchDisabledComponents)
                {
                    if (EditorUtility.GetObjectEnabled(component) == 0)
                    {
                        continue;
                    }
                }

                // skipping ignored components
                if (checkForIgnores)
                {
                    if (Array.IndexOf(MaintainerSettings.Issues.componentIgnores, componentName) != -1)
                    {
                        continue;
                    }
                }

                components.Add(component);
                componentsTypes.Add(componentType);
                componentsNames.Add(componentName);
                componentsFullNames.Add(componentFullName);
                componentsNamespaces.Add(componentNamespace);
                componentsCount++;
            }

            // ----------------------------------------------------------------------------
            // checking stuff related to the prefabs in scenes
            // ----------------------------------------------------------------------------

            if (checkingScene)
            {
                PrefabType prefabType = PrefabUtility.GetPrefabType(go);

                if (prefabType != PrefabType.None)
                {
                    /* checking if we're inside of nested prefab with same type as root,
                     * allows to skip detections of missed and disconnected prefabs children */

                    GameObject rootPrefab            = PrefabUtility.FindRootGameObjectWithSameParentPrefab(go);
                    bool       rootPrefabHasSameType = false;
                    if (rootPrefab != go)
                    {
                        PrefabType rootPrefabType = PrefabUtility.GetPrefabType(rootPrefab);
                        if (rootPrefabType == prefabType)
                        {
                            rootPrefabHasSameType = true;
                        }
                    }

                    if (prefabType == PrefabType.MissingPrefabInstance)
                    {
                        if (MaintainerSettings.Issues.missingPrefabs && !rootPrefabHasSameType)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.MissingPrefab, location, path, go));
                        }
                    }
                    else if (prefabType == PrefabType.DisconnectedPrefabInstance ||
                             prefabType == PrefabType.DisconnectedModelPrefabInstance)
                    {
                        if (MaintainerSettings.Issues.disconnectedPrefabs && !rootPrefabHasSameType)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.DisconnectedPrefab, location, path, go));
                        }
                    }

                    /* checking if this game object is actually prefab instance
                     * without any changes, so we can skip it if we have assets search enabled */

                    if (prefabType != PrefabType.DisconnectedPrefabInstance &&
                        prefabType != PrefabType.DisconnectedModelPrefabInstance &&
                        prefabType != PrefabType.MissingPrefabInstance && MaintainerSettings.Issues.lookInAssets)
                    {
                        bool skipThisPrefabInstance = true;

                        // we shouldn't skip object if it's nested deeper 2nd level
                        if (CSEditorTools.GetDepthInHierarchy(go.transform, rootPrefab.transform) >= 2)
                        {
                            skipThisPrefabInstance = false;
                        }
                        else
                        {
                            PropertyModification[] modifications = PrefabUtility.GetPropertyModifications(go);
                            foreach (PropertyModification modification in modifications)
                            {
                                Object target = modification.target;

                                if (target is Transform)
                                {
                                    continue;
                                }

                                skipThisPrefabInstance = false;
                                break;
                            }
                        }
                        if (skipThisPrefabInstance)
                        {
                            return;
                        }
                    }
                }
            }

            if (MaintainerSettings.Issues.undefinedTags)
            {
                bool undefinedTag = false;
                try
                {
                    if (string.IsNullOrEmpty(go.tag))
                    {
                        undefinedTag = true;
                    }
                }
                catch (UnityException e)
                {
                    if (e.Message.Contains("undefined tag"))
                    {
                        undefinedTag = true;
                    }
                    else
                    {
                        Debug.LogError(Maintainer.LOG_PREFIX + "Unknown error while checking tag of the " + go.name + "\n" + e);
                    }
                }

                if (undefinedTag)
                {
                    issues.Add(GameObjectIssueRecord.Create(RecordType.UndefinedTag, location, path, go));
                }
            }

            if (MaintainerSettings.Issues.unnamedLayers)
            {
                int layerIndex = go.layer;
                if (string.IsNullOrEmpty(LayerMask.LayerToName(layerIndex)))
                {
                    GameObjectIssueRecord issue = GameObjectIssueRecord.Create(RecordType.UnnamedLayer, location, path, go);
                    issue.headerExtra = "(index: " + layerIndex + ")";
                    issues.Add(issue);
                }
            }

            Dictionary <Type, int> uniqueTypes = null;
            List <int>             similarComponentsIndexes = null;

            TerrainData terrainTerrainData         = null;
            TerrainData terrainColliderTerrainData = null;
            bool        terrainChecked             = false;
            bool        terrainColliderChecked     = false;

            // ----------------------------------------------------------------------------
            // looking for component-level issues
            // ----------------------------------------------------------------------------

            for (int i = 0; i < componentsCount; i++)
            {
                Component component     = components[i];
                Type      componentType = componentsTypes[i];
                string    componentName = componentsNames[i];
                //string componentFullName = componentsFullNames[i];
                string componentNamespace = componentsNamespaces[i];

                if (component is Transform)
                {
                    if (MaintainerSettings.Issues.hugePositions)
                    {
                        Vector3 position = (component as Transform).position;

                        if (Math.Abs(position.x) > 100000f || Math.Abs(position.y) > 100000f || Math.Abs(position.z) > 100000f)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.HugePosition, location, path, go, component, componentType, componentName, "Position"));
                        }
                    }
                    continue;
                }

                if (MaintainerSettings.Issues.duplicateComponents &&
                    (componentNamespace != "Fabric"))
                {
                    // initializing dictionary and list on first usage
                    if (uniqueTypes == null)
                    {
                        uniqueTypes = new Dictionary <Type, int>(componentsCount);
                    }
                    if (similarComponentsIndexes == null)
                    {
                        similarComponentsIndexes = new List <int>(componentsCount);
                    }

                    // checking if current component type already met before
                    if (uniqueTypes.ContainsKey(componentType))
                    {
                        int uniqueTypeIndex = uniqueTypes[componentType];

                        // checking if initially met component index already in indexes list
                        // since we need to compare all duplicate candidates against initial component
                        if (!similarComponentsIndexes.Contains(uniqueTypeIndex))
                        {
                            similarComponentsIndexes.Add(uniqueTypeIndex);
                        }

                        // adding current component index to the indexes list
                        similarComponentsIndexes.Add(i);
                    }
                    else
                    {
                        uniqueTypes.Add(componentType, i);
                    }
                }

                if (component is MeshCollider)
                {
                    if (MaintainerSettings.Issues.emptyMeshColliders)
                    {
                        if ((component as MeshCollider).sharedMesh == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyMeshCollider, location, path, go, component, componentType, componentName));
                        }
                    }
                }
                else if (component is MeshFilter)
                {
                    if (MaintainerSettings.Issues.emptyMeshFilters && !skipEmptyMeshFilter)
                    {
                        if ((component as MeshFilter).sharedMesh == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyMeshFilter, location, path, go, component, componentType, componentName));
                        }
                    }
                }
                else if (component is Renderer)
                {
                    if (MaintainerSettings.Issues.emptyRenderers)
                    {
                        if ((component as Renderer).sharedMaterial == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyRenderer, location, path, go, component, componentType, componentName));
                        }
                    }

                    if (component is SpriteRenderer)
                    {
                        if (MaintainerSettings.Issues.emptySpriteRenderers)
                        {
                            if ((component as SpriteRenderer).sprite == null)
                            {
                                issues.Add(GameObjectIssueRecord.Create(RecordType.EmptySpriteRenderer, location, path, go, component, componentType, componentName));
                            }
                        }
                    }
                }
                else if (component is Animation)
                {
                    if (MaintainerSettings.Issues.emptyAnimations)
                    {
                        if ((component as Animation).GetClipCount() <= 0 && (component as Animation).clip == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyAnimation, location, path, go, component, componentType, componentName));
                        }
                    }
                }
                else if (component is Terrain)
                {
                    if (MaintainerSettings.Issues.inconsistentTerrainData)
                    {
                        terrainTerrainData = (component as Terrain).terrainData;
                        terrainChecked     = true;
                    }
                }
                else if (component is TerrainCollider)
                {
                    if (MaintainerSettings.Issues.inconsistentTerrainData)
                    {
                        terrainColliderTerrainData = (component as TerrainCollider).terrainData;
                        terrainColliderChecked     = true;
                    }

                    if (MaintainerSettings.Issues.emptyTerrainCollider)
                    {
                        if ((component as TerrainCollider).terrainData == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyTerrainCollider, location, path, go, component, componentType, componentName));
                        }
                    }
                }
                else if (component is AudioSource)
                {
                    if (MaintainerSettings.Issues.emptyAudioSource && !skipEmptyAudioSource)
                    {
                        if ((component as AudioSource).clip == null)
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.EmptyAudioSource, location, path, go, component, componentType, componentName));
                        }
                    }
                }

                // ----------------------------------------------------------------------------
                // looping through the component's SerializedProperties via SerializedObject
                // ----------------------------------------------------------------------------

                Dictionary <string, int> emptyArrayItems = new Dictionary <string, int>();
                SerializedObject         so = new SerializedObject(component);
                SerializedProperty       sp = so.GetIterator();

                while (sp.NextVisible(true))
                {
                    string fullPropertyPath = sp.propertyPath;

                    bool isArrayItem = fullPropertyPath.EndsWith("]", StringComparison.Ordinal);

                    if (MaintainerSettings.Issues.missingReferences)
                    {
                        if (sp.propertyType == SerializedPropertyType.ObjectReference)
                        {
                            if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0)
                            {
                                string propertyName = isArrayItem ? GetArrayItemNameAndIndex(fullPropertyPath) : sp.name;
                                issues.Add(GameObjectIssueRecord.Create(RecordType.MissingReference, location, path, go, component, componentType, componentName, propertyName));
                            }
                        }
                    }

                    if (checkingScene || !MaintainerSettings.Issues.skipEmptyArrayItemsOnPrefabs)
                    {
                        // skipping SpriteRenderer as it has hidden array with materials of size 1
                        if (MaintainerSettings.Issues.emptyArrayItems && isArrayItem)
                        {
                            // ignoring components where empty array items is a normal behavior
                            if (!(component is SpriteRenderer) && !componentName.StartsWith("TextMeshPro"))
                            {
                                if (sp.propertyType == SerializedPropertyType.ObjectReference &&
                                    sp.objectReferenceValue == null &&
                                    sp.objectReferenceInstanceIDValue == 0)
                                {
                                    string arrayName = GetArrayItemName(fullPropertyPath);

                                    // ignoring TextMeshPro's FontAssetArrays with 16 empty items inside
                                    if (!emptyArrayItems.ContainsKey(arrayName))
                                    {
                                        emptyArrayItems.Add(arrayName, 0);
                                    }
                                    emptyArrayItems[arrayName]++;
                                }
                            }
                        }
                    }

                    /*else
                     * {
                     *      continue;
                     * }*/
                }

                if (MaintainerSettings.Issues.emptyArrayItems)
                {
                    foreach (var item in emptyArrayItems.Keys)
                    {
                        GameObjectIssueRecord issueRecord = GameObjectIssueRecord.Create(RecordType.EmptyArrayItem, location, path, go, component, componentType, componentName, item);
                        issueRecord.headerFormatArgument = emptyArrayItems[item].ToString();
                        issues.Add(issueRecord);
                    }
                }
            }

            if (MaintainerSettings.Issues.inconsistentTerrainData &&
                terrainColliderTerrainData != terrainTerrainData &&
                terrainChecked && terrainColliderChecked)
            {
                issues.Add(GameObjectIssueRecord.Create(RecordType.InconsistentTerrainData, location, path, go));
            }

            if (MaintainerSettings.Issues.duplicateComponents)
            {
                if (similarComponentsIndexes != null && similarComponentsIndexes.Count > 0)
                {
                    int         similarComponentsCount  = similarComponentsIndexes.Count;
                    List <long> similarComponentsHashes = new List <long>(similarComponentsCount);

                    for (int i = 0; i < similarComponentsCount; i++)
                    {
                        int       componentIndex = similarComponentsIndexes[i];
                        Component component      = components[componentIndex];

                        long componentHash = 0;

                        if (MaintainerSettings.Issues.duplicateComponentsPrecise)
                        {
                            SerializedObject   so = new SerializedObject(component);
                            SerializedProperty sp = so.GetIterator();
                            while (sp.NextVisible(true))
                            {
                                componentHash += CSEditorTools.GetPropertyHash(sp);
                            }
                        }

                        similarComponentsHashes.Add(componentHash);
                    }

                    List <long> distinctItems = new List <long>(similarComponentsCount);

                    for (int i = 0; i < similarComponentsCount; i++)
                    {
                        int componentIndex = similarComponentsIndexes[i];

                        if (distinctItems.Contains(similarComponentsHashes[i]))
                        {
                            issues.Add(GameObjectIssueRecord.Create(RecordType.DuplicateComponent, location, path, go, components[componentIndex], componentsTypes[componentIndex], componentsNames[componentIndex]));
                        }
                        else
                        {
                            distinctItems.Add(similarComponentsHashes[i]);
                        }
                    }
                }
            }
        }