MaximilianPs

ReplaceObjectsWithPrefab

Aug 23rd, 2025
328
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.21 KB | Gaming | 0 0
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections.Generic;
  4. using UnityEditor.SceneManagement;
  5. using System.Text.RegularExpressions;
  6.  
  7. public class ReplaceObjectsWithPrefab : EditorWindow
  8. {
  9.     public GameObject prefabToReplaceWith;
  10.     public string targetName = "";
  11.     public bool keepChildren = true;
  12.     public Material overrideMaterial;
  13.  
  14.     [MenuItem("Tools/Replace Objects With Prefab")]
  15.     public static void ShowWindow()
  16.     {
  17.         var window = EditorWindow.GetWindow<ReplaceObjectsWithPrefab>(
  18.             utility: true, // Questo la rende una Utility Window
  19.             title: "Replace Objects"
  20.         );
  21.         window.minSize = new Vector2(400, 200);
  22.         window.maxSize = new Vector2(400, 200);
  23.     }
  24.  
  25.     void OnGUI()
  26.     {
  27.         GUILayout.Label("1. Specify the objects to replace", EditorStyles.boldLabel);
  28.         GUILayout.Label("You can use '*' as a wildcard anywhere in the name.", EditorStyles.miniLabel);
  29.  
  30.         // Layout orizzontale per il campo Target Name e il pulsante Select
  31.         EditorGUILayout.BeginHorizontal();
  32.         targetName = EditorGUILayout.TextField("Target Name", targetName);
  33.         if (GUILayout.Button("Select", GUILayout.Width(60)))
  34.         {
  35.             SelectMatchingObjects();
  36.         }
  37.         EditorGUILayout.EndHorizontal();
  38.  
  39.         EditorGUILayout.Space();
  40.  
  41.         GUILayout.Label("2. Specify the prefab to replace with", EditorStyles.boldLabel);
  42.         prefabToReplaceWith = (GameObject)EditorGUILayout.ObjectField("Prefab", prefabToReplaceWith, typeof(GameObject), false);
  43.         EditorGUILayout.Space();
  44.  
  45.         GUILayout.Label("3. Material Override (Optional)", EditorStyles.boldLabel);
  46.         overrideMaterial = (Material)EditorGUILayout.ObjectField("New Material", overrideMaterial, typeof(Material), false);
  47.         EditorGUILayout.Space(10);
  48.  
  49.         keepChildren = GUILayout.Toggle(keepChildren, "Keep Children of replaced objects");
  50.  
  51.         if (GUILayout.Button("Replace All"))
  52.         {
  53.             ReplaceObjects();
  54.         }
  55.     }
  56.  
  57.     // Funzione per verificare se un nome corrisponde a un pattern con wildcard
  58.     private bool MatchesWildcardPattern(string name, string pattern)
  59.     {
  60.         // Convertiamo il pattern con wildcard in un'espressione regolare
  61.         string regexPattern = "^" + Regex.Escape(pattern).Replace("\\*", ".*") + "$";
  62.         Regex regex = new Regex(regexPattern);
  63.         return regex.IsMatch(name);
  64.     }
  65.  
  66.     // Nuova funzione per selezionare gli oggetti corrispondenti al pattern
  67.     private void SelectMatchingObjects()
  68.     {
  69.         if (string.IsNullOrEmpty(targetName))
  70.         {
  71.             EditorUtility.DisplayDialog("⚠️ Warning ⚠️", "The 'Target Name' field cannot be empty.", "Ok");
  72.             return;
  73.         }
  74.  
  75.         string trimmedTargetName = targetName.Trim();
  76.         List<GameObject> matchingObjects = new List<GameObject>();
  77.         var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
  78.  
  79.         if (prefabStage != null)
  80.         {
  81.             Debug.Log("Prefab mode: 🔍 Searching for objects...");
  82.             GameObject root = prefabStage.prefabContentsRoot;
  83.             var allTransforms = root.GetComponentsInChildren<Transform>(true);
  84.             foreach (var t in allTransforms)
  85.             {
  86.                 if (MatchesWildcardPattern(t.name, trimmedTargetName))
  87.                 {
  88.                     matchingObjects.Add(t.gameObject);
  89.                 }
  90.             }
  91.         }
  92.         else
  93.         {
  94.             Debug.Log("Scene Mode: 🔍 Finding objects...");
  95.             var allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
  96.             foreach (var obj in allObjects)
  97.             {
  98.                 if (!obj.scene.IsValid()) continue;
  99.                 if (MatchesWildcardPattern(obj.name, trimmedTargetName))
  100.                 {
  101.                     matchingObjects.Add(obj);
  102.                 }
  103.             }
  104.         }
  105.  
  106.         if (matchingObjects.Count == 0)
  107.         {
  108.             EditorUtility.DisplayDialog("Info", "No objects found matching the specified criteria.", "Ok");
  109.             return;
  110.         }
  111.  
  112.         // Imposta la selezione sugli oggetti trovati
  113.         Selection.objects = matchingObjects.ToArray();
  114.  
  115.         string contextMessage = (prefabStage != null) ? "in the prefab." : "in the scene.";
  116.         EditorUtility.DisplayDialog("Selection Complete", $"Selected {matchingObjects.Count} {contextMessage} objects", "Ok");
  117.         Debug.Log($"Selected {matchingObjects.Count} objects matching '{trimmedTargetName}'.");
  118.     }
  119.  
  120.     void ReplaceObjects()
  121.     {
  122.         if (prefabToReplaceWith == null)
  123.         {
  124.             EditorUtility.DisplayDialog("⚠️ Warning ⚠️", "No Prefab assigned!", "Ok");
  125.             return;
  126.         }
  127.  
  128.         if (string.IsNullOrEmpty(targetName))
  129.         {
  130.             EditorUtility.DisplayDialog("⚠️ Warning ⚠️", "The 'Target Name' field cannot be empty.", "Ok");
  131.             return;
  132.         }
  133.  
  134.         string prefabName = prefabToReplaceWith.name;
  135.         List<GameObject> objectsToReplace = new List<GameObject>();
  136.         var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
  137.         string trimmedTargetName = targetName.Trim();
  138.  
  139.         if (prefabStage != null)
  140.         {
  141.             Debug.Log("Prefab mode: 🔍 Searching for objects...");
  142.             GameObject root = prefabStage.prefabContentsRoot;
  143.             var allTransforms = root.GetComponentsInChildren<Transform>(true);
  144.             foreach (var t in allTransforms)
  145.             {
  146.                 if (t.gameObject == prefabToReplaceWith) continue;
  147.  
  148.                 // Usa la nuova funzione per verificare la corrispondenza con le wildcard
  149.                 if (MatchesWildcardPattern(t.name, trimmedTargetName))
  150.                 {
  151.                     objectsToReplace.Add(t.gameObject);
  152.                 }
  153.             }
  154.         }
  155.         else
  156.         {
  157.             Debug.Log("Scene Mode: 🔍 Finding objects...");
  158.             var allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
  159.             foreach (var obj in allObjects)
  160.             {
  161.                 if (!obj.scene.IsValid() || obj == prefabToReplaceWith) continue;
  162.  
  163.                 // Usa la nuova funzione per verificare la corrispondenza con le wildcard
  164.                 if (MatchesWildcardPattern(obj.name, trimmedTargetName))
  165.                 {
  166.                     objectsToReplace.Add(obj);
  167.                 }
  168.             }
  169.         }
  170.  
  171.         if (objectsToReplace.Count == 0)
  172.         {
  173.             EditorUtility.DisplayDialog("Info", "No objects found to replace with the specified criteria.", "Ok");
  174.             return;
  175.         }
  176.  
  177.         Undo.SetCurrentGroupName("Replace Objects With Prefab");
  178.         int group = Undo.GetCurrentGroup();
  179.  
  180.         foreach (var obj in objectsToReplace)
  181.         {
  182.             if (obj == null) continue;
  183.  
  184.             Transform originalTransform = obj.transform;
  185.             List<Transform> children = null;
  186.  
  187.             if (keepChildren)
  188.             {
  189.                 children = new List<Transform>();
  190.                 foreach (Transform child in originalTransform)
  191.                 {
  192.                     children.Add(child);
  193.                 }
  194.  
  195.                 foreach (Transform child in children)
  196.                 {
  197.                     Undo.SetTransformParent(child, null, "Unparent Children");
  198.                 }
  199.             }
  200.  
  201.             var targetScene = (prefabStage != null) ? prefabStage.scene : obj.scene;
  202.             GameObject newObj = (GameObject)PrefabUtility.InstantiatePrefab(prefabToReplaceWith, targetScene);
  203.             Undo.RegisterCreatedObjectUndo(newObj, "Create New Prefab");
  204.  
  205.             newObj.transform.SetParent(originalTransform.parent);
  206.             newObj.transform.position = originalTransform.position;
  207.             newObj.transform.rotation = originalTransform.rotation;
  208.             newObj.transform.localScale = originalTransform.localScale;
  209.  
  210.             // --- NUOVA LOGICA PER APPLICARE IL MATERIALE ---
  211.             if (overrideMaterial != null)
  212.             {
  213.                 // Cerca tutti i Renderer nel nuovo prefab e nei suoi figli
  214.                 var renderers = newObj.GetComponentsInChildren<Renderer>(true);
  215.                 foreach (var renderer in renderers)
  216.                 {
  217.                     // Registra l'oggetto per l'Undo PRIMA di modificarlo
  218.                     Undo.RecordObject(renderer, "Apply Override Material");
  219.                     renderer.material = overrideMaterial;
  220.                 }
  221.             }
  222.  
  223.             if (keepChildren && children != null)
  224.             {
  225.                 foreach (Transform child in children)
  226.                 {
  227.                     Undo.SetTransformParent(child, newObj.transform, "Reparent Children");
  228.                 }
  229.             }
  230.  
  231.             Undo.DestroyObjectImmediate(obj);
  232.         }
  233.  
  234.         Undo.CollapseUndoOperations(group);
  235.         string contextMessage = (prefabStage != null) ? "in the prefab." : "in the scene.";
  236.         EditorUtility.DisplayDialog("Operation Complete", $"Replaced {objectsToReplace.Count} {contextMessage} objects", "Ok");
  237.         Debug.Log($"Replaced {objectsToReplace.Count} objects matching '{targetName}' with the prefab '{prefabName}'.");
  238.     }
  239. }
Advertisement
Add Comment
Please, Sign In to add comment