반응형

쫌 꼼수지만 아래와 같이 작동한다.


참조 바로가기 

        PrefabUtility.DisconnectPrefabInstance(obj);
        Object prefab = PrefabUtility.CreateEmptyPrefab("Assets/dummy.prefab");
        PrefabUtility.ReplacePrefab(obj, prefab, ReplacePrefabOptions.ConnectToPrefab);
        PrefabUtility.DisconnectPrefabInstance(obj);
        AssetDatabase.DeleteAsset("Assets/dummy.prefab");


반응형
반응형

계층뷰 상의 여러개의 프리펩 오브젝트들을 한번 Apply 하는 것을 제작 하였습니다.


사용방법은 아래와 같습니다.

1. 계층 뷰에서 갱신할 프리펩 오브젝트들을 선택합니다.

본문 이미지 1

2. 마우스 오른쪽을 클릭하여 CustomMenu > Apply Prefabs를 클릭하면 여러개의 프리펩

오브젝트들이 원클릭에 갱신이 실행됩니다.

본문 이미지 2

잘못 선택된 프리펩이아닌 오브젝트는 무시하고
부모가 아닌 프리펩의 차일들을 선택 되었을때 부모를 찾아 중복 체크를 하여 하나만 갱신됩니다.

PS. 보너스로 JGUI도 마우스 오른쪽 클릭 메뉴 아이템으로 옮겨 두었습니다.


  
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

public class csPrefabApplyer
{
    [MenuItem("GameObject/CustomMenu/Apply Prefabs", false, 0)]
    static void Init(MenuCommand menuCommand)
    {
        if (Selection.objects.Length > 0)
        {
            if (menuCommand.context == Selection.objects[0])
            {
                GameObject[] prefabs = Selection.gameObjects;

                Dictionary _prefabDicList = new Dictionary();
                for (int i = 0; i < prefabs.Length; i++)
                {
                    // 프리펩이 아닌 오브젝트는 무시
                    if (PrefabUtility.GetPrefabParent(prefabs[i]) != null)
                    {
                        // 최상위 부모가 아닐때 최상위 부모를 검색하여 추가
                        GameObject root = PrefabUtility.FindRootGameObjectWithSameParentPrefab(prefabs[i]);
                        if (!_prefabDicList.ContainsKey(root.name))
                        {
                            _prefabDicList.Add(root.name, root);
                        }
                    }
                    else if (PrefabUtility.GetPrefabParent(prefabs[i]) == null && PrefabUtility.GetPrefabObject(prefabs[i]) != null)
                    {
                        // 최상위 부모일때 추가
                        GameObject target = PrefabUtility.GetPrefabObject(prefabs[i]) as GameObject;
                        if (!_prefabDicList.ContainsKey(target.name))
                        {
                            _prefabDicList.Add(target.name, target);
                        }
                    }
                }

                // 갱신
                foreach (KeyValuePair prefab in _prefabDicList)
                {
                    PrefabUtility.ReplacePrefab(prefab.Value, PrefabUtility.GetPrefabParent(prefab.Value), ReplacePrefabOptions.ConnectToPrefab);
                }
                return;
            }
        }
    }
}


반응형
반응형
  1. How to execute MenuItem for multiple objects once.


여러개의 오브젝트 선택후 MenuItem을 실행 하면 오브젝트 수만큼 해당 함수가 실행 되는데
이를 아래와 같이 막을수있다.


  1. static public void MethodName(MenuCommand menuCommand)
  2. {
  3. //Prevent executing multiple times when right-clicking.
  4. if (Selection.objects.Length > 1)
  5. {
  6. if (menuCommand.context != Selection.objects[0])
  7. {
  8. return;
  9. }
  10. }
  11. }


윗코드에선 두개의 오브젝트를 선택했을때 첫번째 인덱스 0의 오브젝트와 같으면 패스하게 되고 나머지 오브젝트들을 다실행하는데 하나만 실행 되게 하기 위해선 아래와 같이 수정이 필요 했다.



        if (Selection.objects.Length > 0)
        {
            if (menuCommand.context == Selection.objects[0])
            {
                    return;
            }
        }
반응형
반응형

동적 프리펩 갱신 아래를 사용하자


  PrefabUtility.ReplacePrefab( go, PrefabUtility.GetPrefabParent( go ), ReplacePrefabOptions.ConnectToPrefab );


using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 #if UNITY_EDITOR
 using UnityEditor;
 #endif
 
 public class UnitEditorBulkApply : MonoBehaviour, ICheckForUnsafeChanges
 {
     public bool resetPosition = true;
     public bool resetScale = true;
     public bool resetRotation = true;
 
 
 #if UNITY_EDITOR
     [ContextMenu("Apply Bulk Prefab Apply")]
     public void CheckForUnsafeChanges()
     {
         for ( int i = 0; i < transform.childCount; i++)
         {
             GameObject go = transform.GetChild( i ).gameObject;
 
             if ( PrefabUtility.GetPrefabParent( go ) != null )
             {
                 Vector3 pos = go.transform.localPosition;
                 Vector3 scale = go.transform.localScale;
                 Quaternion rot = go.transform.localRotation;
 
                 if ( resetPosition ) go.transform.localPosition = Vector3.zero;
                 if ( resetScale ) go.transform.localScale = Vector3.one;
                 if ( resetRotation ) go.transform.localRotation = Quaternion.identity;
 
                 {
                     MonoBehaviour [] behaviours = go.GetComponents<MonoBehaviour>();
                     foreach ( MonoBehaviour b in behaviours )
                         if ( b is ICheckForUnsafeChanges )
                             ( b as ICheckForUnsafeChanges ).CheckForUnsafeChanges();
                 }
 
                 Debug.Log( "Applying changes to " + go.name, go );
                 PrefabUtility.ReplacePrefab( go, PrefabUtility.GetPrefabParent( go ), ReplacePrefabOptions.ConnectToPrefab );
 
                 if ( resetPosition ) go.transform.localPosition = pos;
                 if ( resetScale ) go.transform.localScale = scale;
                 if ( resetRotation ) go.transform.localRotation = rot;
             }
         }
     }
 #endif
 }
 
 public interface ICheckForUnsafeChanges {
 #if UNITY_EDITOR
     void CheckForUnsafeChanges();
 #endif
 }


반응형

+ Recent posts