유니티에서 오브젝트를 30개 이상 복사해야 할때가 가끔 있다.

예를 들어, 아래 이미지처럼 UI에서 업적, 도감 등등에서 미리 Image 오브젝트를 만들어 놓는 경우가 있다.

UI에 사용되는 이미지 depth가 얼마나 되느냐에 따라 복제해야 될 오브젝트들은 점점 많아진다.


하지만 유니티에서 복제(Ctrl+D) 사용시 네이밍이 생각보다 안좋다.

아래 그림처럼 Img_Container_33을 Ctrl+D를 사용하여 복제 하였을 경우 'Img_Container_33 (1)', 'Img_Container_33 (2)', 'Img_Container_33 (3)' 이런식으로 늘어나게 되어 이름을 바꾸는데 시간이 너무 오래 걸린다.



그래서 구글링한 결과 비슷한 스크립트가 있었는데, 사용한 결과 아래 이미지처럼 ' (1)' ' (2)'를 제외하고 원본의 이름을 그대로 가져가도록 설정되어 있었다.



그래서 새로운 단축키를 만들어서 오브젝트 복제시 10개씩 복제되면서, 네이밍도 자연스럽게 변경되도록 스크립트를 변경하였다.

Img_Container_33을 복제하니 Img_Container_43까지 네이밍만 변경되어 생성되었다.


먼저, 참고한 스크립트는 아래의 DupWithoutRename과 같다. (원본 링크)

DupWithoutRename.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/// <summary>
/// DupWithoutRename is a utility class for Unity 5 that mimics the Unity 4 behavior of Ctrl+D (or Cmd+D on Mac): objects are duplicated 
/// without being renamed. In Unity 5 they are renamed automatically, and it sucks. Place this file in Assets/Editor so that it is 
/// detected as an editor script.
/// 
/// Note that unlike the real Ctrl+D command, this one only duplicates objects in the scene hierarchy.
/// It can't duplicate other stuff, like assets in your Project database, or array entries in the editor's stock array manager GUI. 
/// For this reason, it's mapped to Ctrl+Shift+D, so you still have access to Ctrl+D for those other tasks.
/// 
/// v1.01. 
/// Code by Eric Heimburg. 
/// Public domain. This is free and unencumbered software released into the public domain. See unlicense.org for details.
/// </summary>
 
// Known issue!!! While this function will duplicate selected prefabs correctly, if you duplicate a NON-prefab game object that has child objects
// that ARE prefabs, the duplicated children won't be correctly marked as prefabs. This scenario doesn't seem to occur in practice for me,
// which is good because I don't have time to try to fix it at the moment. If somebody fixes it, though, please email me! eric@heimburg.com
 
using UnityEngine;
using UnityEditor;
 
public class DupWithoutRename 
{
    [MenuItem("GameObject/Duplicate Without Renaming %#d")]
    public static void DuplicateWithoutRenaming()
    {
        foreach (Transform t in Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable))
        {
            GameObject newObject = null;
 
            PrefabType pt = PrefabUtility.GetPrefabType(t.gameObject);
            if (pt == PrefabType.PrefabInstance || pt == PrefabType.ModelPrefabInstance)
            {
                // it's an instance of a prefab! Create a new instance of the same prefab!
                Object prefab = PrefabUtility.GetPrefabParent(t.gameObject);
                newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
 
                // we've got a brand new prefab instance, but it doesn't have the same overrides as our original. Fix that...
                PropertyModification[] overrides = PrefabUtility.GetPropertyModifications(t.gameObject);
                PrefabUtility.SetPropertyModifications(newObject, overrides);
            }
            else
            {
                // not a prefab... so just instantiate it!
                newObject = Object.Instantiate(t.gameObject);
                newObject.name = t.name;
            }
 
            // okay, prefab is instantiated (or if it's not a prefab, we've just cloned it in the scene)
            // Make sure it's got the same parent and position as the original!
            newObject.transform.parent = t.parent;
            newObject.transform.position = t.position;
            newObject.transform.rotation = t.rotation;
 
            // tell the Undo system we made this, so you can undo it if you did it by mistake
            Undo.RegisterCreatedObjectUndo(newObject, "Duplicate Without Renaming");
        }
    }
    
    
    [MenuItem("GameObject/Duplicate Without Renaming %#d"true)]
    public static bool ValidateDuplicateWithoutRenaming()
    {
        return Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable).Length > 0;
    }
 
}
 
cs



유니티에 스크립트를 삽입하면, 아래 좌측 그림처럼 GameObject 하위메뉴에 Duplicate Without Renaming Ctrl+Shift+D 로 등록된다.

오브젝트를 선택하고 Ctrl+Shift+D를 누르면, 아래 우측그림 처럼 Img_Container_33을 그대로 복사하여 Img_Container_33으로 1개 복제해 준다.



위의 스크립트를 변경한것은 아래의 DupWithNumbering과 같다.

위와의 변경점은 넘버링을 추가하였고, 복제시 Scale이 변경되버리는 문제점 때문에 Scale도 Original Object를 따라가도록 추가하였다.

DupWithNumbering.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using UnityEngine;
using UnityEditor;
 
public class DupWithNumbering : MonoBehaviour {
 
    [MenuItem("GameObject/Duplicate With Numbering by ten %#v")]
    public static void DuplicateWithNumbering()
    {
        foreach (Transform t in Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable))
        {
            GameObject newObject = null;
 
            PrefabType pt = PrefabUtility.GetPrefabType(t.gameObject);
            if (pt == PrefabType.PrefabInstance || pt == PrefabType.ModelPrefabInstance)
            {
                // it's an instance of a prefab! Create a new instance of the same prefab!
                Object prefab = PrefabUtility.GetPrefabParent(t.gameObject);
                newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
 
                // we've got a brand new prefab instance, but it doesn't have the same overrides as our original. Fix that...
                PropertyModification[] overrides = PrefabUtility.GetPropertyModifications(t.gameObject);
                PrefabUtility.SetPropertyModifications(newObject, overrides);
                
                //// okay, prefab is instantiated (or if it's not a prefab, we've just cloned it in the scene)
                //// Make sure it's got the same parent and position as the original!
                newObject.transform.parent = t.parent;
                newObject.transform.position = t.position;
                newObject.transform.rotation = t.rotation;
            }
            else
            {
                for (int i = 1; i <= 10; i++)
                {
                    // not a prefab... so just instantiate it!
                    newObject = Object.Instantiate(t.gameObject);
 
                    //always first object name of end with _01
                    string originalName = t.name;
                    string nameWithoutNumber = originalName.Substring(0, originalName.Length - 2);
                    int startNumber = int.Parse(originalName.Substring(originalName.Length - 22));
 
                    //numbering example : _01, _02, _03 ... _10
                    originalName = string.Format("{0}{1:00}", nameWithoutNumber, startNumber + i);
                    newObject.name = originalName;
 
                    newObject.transform.parent = t.parent;
                    newObject.transform.position = t.position;
                    newObject.transform.rotation = t.rotation;
                    newObject.transform.localScale = t.localScale;
                }
            }
            // tell the Undo system we made this, so you can undo it if you did it by mistake
            Undo.RegisterCreatedObjectUndo(newObject, "Duplicate Without Renaming");
        }
    }
 
    [MenuItem("GameObject/Duplicate Without Renaming by ten %#v"true)]
    public static bool ValidateDuplicateWithNumbering()
    {
        return Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable).Length > 0;
    }
}
 
cs




위 스크립트를 유니티에 삽입하면, 아래 좌측 그림처럼 GameObject 하위메뉴에 Duplicate With Numbering by ten Ctrl+Shift+V 로 등록된다.

오브젝트를 선택하고 Ctrl+Shift+V를 누르면, 아래 우측그림 처럼 Img_Container_33을 복사하여 Img_Container_43까지 넘버링하여 10개 복제해 준다.



DupWithNumbering 사용시 주의점이 몇가지 있다.

1. 프리펩은 테스트하지 않았다. (DupWithoutRename도 마찬가지이다.)

2. 넘버링을 매길 오브젝트는 끝자리에 넘버링을 매겨야하며, 끝자리는 2자리 숫자로 되어있어야 한다. (예시 : btn_00, img_00, txt_00)



넘버링을 위치를 앞으로 하고 싶다면 37줄 ~ 43줄을 고치고,

개수를 변경하고 싶다면 32번줄의 for문을 고치면 된다.

+ Recent posts