Search Unity

Replace an object in a prefab with another prefab?

Discussion in 'Scripting' started by zergmouse, Sep 14, 2012.

  1. zergmouse

    zergmouse

    Joined:
    Jun 30, 2010
    Posts:
    216
    Ok here is what I want to do. I have a Maya model which is a room with several cubes in it. Then I have a library (folder) of complex models (also Maya). I am using PostProcessForMaya : AssetPostprocessor to do things like find all cubes with the name PointLight and delete their mesh, colliders, and renderer then attach a light component and set its attributes. Now when I drag that into my project I have lights. So far all of that is working. And I am trying to avoid creating a prefab in another folder with all the added or changed things. I don't like the idea of duplicate data.

    But the second thing I wanted to do was find all cubes named "Desk" and replace them with detailed desk models. The problem is that I cannot just make the cube's transform equal the desk transform because the desk is made up of several smaller parts. SO this is not working. All I want is to take a cube and replace it with a desk. I have already figured out how to create an empty GO, Instantiate the Office model, replace cubes with desks, and save it back as a prefab to my library. But again, that is now duplicate data. I plan on these files getting very large, on the verge of crashing Unity (where is x64 editor? lol), so having duplicates is a bad idea.

    Also, I am aware that there are packages on the asset store that do this sort of thing. But I will need very granular control over this script for other reasons. Also working for a corporation means I cant just go pick up a package without signing a lot of internal paperwork, doing a security assessment, getting an IT concur/ review, talking to lawyers about licenses, and finally getting purchasing involved to maintain the license. So purchasing a package from the Unity store that does this sort of thing is out of scope of my project.

    Anyways, here is the code. It is a little messy but that is because it is still very much a work in progress. Any help would be appreciated.
    Code (csharp):
    1.  
    2. //-------------------------------------------//
    3. //
    4. // Place this in a folder named "Editor"
    5. //
    6. //-------------------------------------------//
    7.  
    8. using UnityEngine;
    9. using UnityEditor;
    10. using System.Collections;
    11. using System.Text.RegularExpressions;
    12. using System.IO;
    13. using System;
    14.  
    15. public class PostProcessForMaya : AssetPostprocessor
    16. {
    17.     private string flStructures = "/[ModEls]/StruCturEs/"; //Not case sensitive, we convert everything ToLower later
    18.  
    19.     //strings for naming conventions. Mostly here so I can use .ToLower() on them
    20.     private string sLight = "Light";
    21.     private string sDeskPlaceHolder = "DeskPlaceHolder";
    22.  
    23.     private void OnPostprocessModel(GameObject g)
    24.     {
    25.         string lowerCaseAssetPath = assetPath.ToLower();
    26.         if (lowerCaseAssetPath.IndexOf(flStructures.ToLower()) == -1)
    27.             return; //If it is not in the structures folder we wont post-process it
    28.  
    29.         //Do something to each file found in the folder
    30.         Apply(g.transform);
    31.         //Lets make sure the devs know something just happened
    32.         Debug.Log(g.name + " has just been post-processed on " + DateTime.Now.ToString("dddd, dd-MMM-yyyy") + " at " + DateTime.Now.ToString("hh:mm tt"));
    33.     }
    34.  
    35.     private void Apply(Transform transform)
    36.     {
    37.         //Make everything static for lightmapping
    38.         transform.gameObject.isStatic = true;
    39.        
    40.         //Look for lights...
    41.         if (transform.name.ToLower().Contains(sLight.ToLower()))
    42.             LightRules(transform);
    43.  
    44.         //Replace Desks
    45.         if (transform.name.ToLower().Contains(sDeskPlaceHolder.ToLower()))
    46.             DeskRules(transform.gameObject);
    47.  
    48.         foreach (Transform child in transform)
    49.             Apply(child); //cycle through all children of the current transform
    50.     }
    51.  
    52.     private void LightRules(Transform transform)
    53.     {
    54.         //Remove colliders. Not needed for lights.
    55.         //Had to use UnityEngine.Object because we are also using "using.System" which has an Object reference
    56.         Component[] mr = transform.gameObject.GetComponentsInChildren(typeof(MeshRenderer), true);
    57.         foreach (MeshRenderer o in mr) { UnityEngine.Object.DestroyImmediate(o, true); }
    58.         Component[] mf = transform.gameObject.GetComponentsInChildren(typeof(MeshFilter), true);
    59.         foreach (MeshFilter o in mf) { UnityEngine.Object.DestroyImmediate(o, true); }
    60.         Component[] mc = transform.gameObject.GetComponentsInChildren(typeof(MeshCollider), true);
    61.         foreach (MeshCollider o in mc) { UnityEngine.Object.DestroyImmediate(o, true); }
    62.  
    63.         //If it has a renderer then make it a light
    64.         transform.gameObject.AddComponent(typeof(Light));
    65.         //Set the light properties
    66.         transform.light.type = LightType.Point;
    67.         transform.light.shadows = LightShadows.Soft;
    68.         transform.light.shadowBias = 0.002f;
    69.         transform.light.intensity = 0.25f;
    70.         transform.light.range = 6.0f;
    71.     }
    72.  
    73.     private void DeskRules(GameObject g)
    74.     {
    75.         // create an empty gameobject and add the mesh as a child
    76.         UnityEngine.Object prefab = (UnityEngine.Object)Resources.Load("Library/Desk_L_Small");
    77.         //GameObject newGO = Instantiate (gameObject, Vector3.zero, Quaternion.Identity);
    78.         //transform = prefabRoot.transform;
    79.  
    80.         //UnityEngine.Object newObject;
    81.         //newObject = (GameObject)Resources.Load("Library/Desk_L_Small");
    82.  
    83.         // create the prefab, and connect the dummy prefab root to it
    84.         PrefabUtility.ReplacePrefab(g, prefab, ReplacePrefabOptions.ReplaceNameBased);
    85.         //EditorUtility.ReplacePrefab(prefabRoot, prefab, ReplacePrefabOptions.ConnectToPrefab);
    86.  
    87.         Debug.Log("Processing Desk");
    88.         //GameObject newObject;
    89.         //PrefabUtility.InstantiatePrefab(newObject);
    90.         //GameObject.Instantiate(newObject,transform.position,transform.rotation);
    91.         //newObject.transform.position = transform.position;
    92.         //newObject.transform.rotation= transform.rotation;
    93.         //newObject.transform.parent = transform.parent;
    94.         //newObject.transform.name = transform.name;
    95.  
    96.         //cleanup the gameobject instance in the scene
    97.         //UnityEngine.Object.DestroyImmediate(prefabRoot);
    98.     }
    99. }
    100.