//Will look at a variable of a given component an checks, whether it references a GameObject or Component present in the hierarchyMapping //Stores any found references private void FindReferencesOn <T>(FindReferenceBaseParameter param, Dictionary <GameObject, List <T> > hierarchyMapping, GetHierarchyFor <T> getHierarchyFor) { List <T> hierarchyAsList; //Current value of the component's variable //May be a list. For simplicity, a list is always assumed var value = GetValueAsListFor <T>(param.ComponentWithReference, param.ReferenceOnTarget, param.IsList); foreach (GameObject targetObject in param.TargetObjects) { if (hierarchyMapping.ContainsKey(targetObject)) { hierarchyAsList = hierarchyMapping[targetObject]; } else { hierarchyAsList = getHierarchyFor(targetObject); hierarchyMapping.Add(targetObject, hierarchyAsList); } for (int i = 0; i < value.Count; i++) { if (hierarchyAsList.Any(o => o.Equals(value[i]))) { if (typeof(T) == typeof(Component)) { StoreReferenceForComponent(targetObject, param.ComponentWithReference, param.ReferenceOnTarget, value[i] as Component, param.IsList, i); } if (typeof(T) == typeof(GameObject)) { StoreReferenceForObject(targetObject, param.ComponentWithReference, param.ReferenceOnTarget, value[i] as GameObject, param.IsList, i); } } } } }
//Searches all components in the scene for references onto the object being replaced //All references will be saved and restored after replacement private void FindExternalReferences() { var allObjectsInScene = FindAllObjects(); var allComponentsInScene = allObjectsInScene.SelectMany(s => GameObjectHelper.GetComponentsSafe <Component>(s)).Where(c => c.GetType().Namespace != "UnityEngine").ToList(); var componentToFieldsMapping = new Dictionary <Type, List <FieldInfo> >(); allComponentsInScene.Select(c => c.GetType()).Distinct().ToList().ForEach(t => componentToFieldsMapping.Add(t, GetFieldsForType(t))); //All objects that may potentially be referenced by other objects var targetObjects = new List <GameObject>(); targetObjects.Add(brokenPrefab); targetObjects.AddRange(similarObjects.Where(s => s.IsActivated).Select(s => s.SimilarObject)); //Stores the children (value) of a gameObject (key) as list //Is a lookup table filled by the FindByReferencesOn function to save some processing time var objectHierarchyMapping = new Dictionary <GameObject, List <GameObject> >(); //Stores the components (value) of a gameObject (key) as list var componentHierarchyMapping = new Dictionary <GameObject, List <Component> >(); //Iterate through every variable of every component in the scene to check whether they may be referencing one of the replaced objects foreach (Component potentiallyTargetingComponent in allComponentsInScene) { foreach (FieldInfo potentialReference in componentToFieldsMapping[potentiallyTargetingComponent.GetType()]) { var componentFieldType = potentialReference.FieldType; var baseParameter = new FindReferenceBaseParameter() { ComponentWithReference = potentiallyTargetingComponent, ReferenceOnTarget = potentialReference, TargetObjects = targetObjects }; if (componentFieldType.IsAssignableFrom(typeof(GameObject))) { baseParameter.IsList = false; FindReferencesOn <GameObject>(baseParameter, objectHierarchyMapping, GameObjectHelper.ObjectHierarchyFor); } if (componentFieldType.IsSubclassOf(typeof(Component))) { baseParameter.IsList = false; FindReferencesOn <Component>(baseParameter, componentHierarchyMapping, GameObjectHelper.ComponentHierarchyFor); } if (IsListOf <GameObject>(componentFieldType)) { baseParameter.IsList = true; FindReferencesOn <GameObject>(baseParameter, objectHierarchyMapping, GameObjectHelper.ObjectHierarchyFor); } if (IsListOf <Component>(componentFieldType)) { baseParameter.IsList = true; FindReferencesOn <Component>(baseParameter, componentHierarchyMapping, GameObjectHelper.ComponentHierarchyFor); } } } }