본문 바로가기
Engine/UNITY

유니티 스크립트 - 이름 찾기 / 하위 오브젝트 뒤지는 재귀함수 사용법

by tartist 2016. 8. 4.

이번에 기존에 등록된 스크립트를 제거하고 새로운 스크립트를 등록하는 툴을 유니티 스크립트로 제작하게 됐는데 이번 툴을 제작하면서 C#에서의 이름 찾기와 재귀 함수 사용법에 대해서 알게 됐습니다.

 

아래 스크립트는 기존 있던  Animated_Death 컴포넌트를 삭제하고 Animated_Death_Combine 이라는 새로운 컴포넌트를 추가하면서 해당 컴포넌트에 하위 오브젝트들의 이름을 뒤져 필요한 Transform을 이름으로 검색하여 자동으로 넣어주는 툴입니다.

아래 스크립트를 참고하면 여러가지 응용이 가능할거 같습니다.

 

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

public class AnimateDeathChange : EditorWindow
{
    GameObject Target = null;
    GameObject pObj = null;

    string strScript = "Animated_Death_Combine";

    string DelScript = "Animated_Death";

    [MenuItem("RK Tools/Art/AnimateDeathChange")]

    //윈도우 생성
    static void InitWindow () 
    {
        AnimateDeathChange window = (AnimateDeathChange)EditorWindow.GetWindow(typeof(AnimateDeathChange));
        window.autoRepaintOnSceneChange = true;

        if (window == null)
        {
            Debug.Log("error: cannot find Dummy");
        }
    }

    //오브젝트 선택창
    void OnGUI()
    { 
        SelectTargetObject ();
        ScriptSetting ();
    }


    //원본소스 선택창
    void SelectTargetObject()
    {
        GUILayout.Space(16f);
        GUI.contentColor = Color.white;
        EditorGUILayout.LabelField("해당 모델에 죽기 스크립트를 추가해 줍니다.");
        EditorGUILayout.LabelField("각각의 항목을 채워주세요.");

        EditorGUILayout.BeginVertical("box");
        Target = (GameObject)EditorGUILayout.ObjectField("Base Model (Project)", Target, typeof(GameObject), false);
        strScript = EditorGUILayout.TextField ( "Add Script Name", strScript);
        DelScript = EditorGUILayout.TextField ( "Del Script Name", DelScript);
        EditorGUILayout.EndVertical();
    }

    //복사 오브젝트는 하이어라키 창에서 실시간 교체 가능
    void OnSelectionChange()
    {        
        if (Selection.gameObjects == null || Selection.gameObjects.Length < 1) {
            Focus();
            Target = null;
            return;
        }

        if (Target != Selection.gameObjects[0])
        {
            Target = Selection.gameObjects[0];
            Focus();           
        }
        else
            Target = Selection.gameObjects[0];
    }

    //실행시 기존 스크     
    void ScriptSetting()
    {
        GUILayout.Space(16f);
        if (GUILayout.Button ("Set Script To Object")) 
        {

            // 새로운 컴포넌트를 넣어주는 명령어 
            UnityEngineInternal.APIUpdaterRuntimeServices.AddComponent(Target, "Assets/Scripts/Editor/Art/AnimateDeathChange.cs", strScript);

            SerchObjectsInChild(Target.transform);

            // 기존 컴포넌트를 제거해주는 명령어
            GameObject.DestroyImmediate (Target.GetComponentInChildren<Animated_Death>());
            GameObject.DestroyImmediate (Target.GetComponentInChildren<Animated_Death>());
            GameObject.DestroyImmediate (Target.GetComponentInChildren<Animated_Death>());




            if (null == Target)
                return;
            if (null == pObj)
                return;
            else 
            {
                SerchObjectsInChild(Target.transform);
            }


        }
    }
    //
    //    //원본 오브젝트의 하위 더미를 찾는 재귀 함수
    private void SerchObjectsInChild(Transform tr)
    {
        int iCount = tr.childCount;

        for (int i = 0; i < iCount; ++i) {
            Transform tempTr = tr.GetChild (i);
//            Debug.Log (tempTr);

            // Contains 명령어는 문장을 뒤져 해당 텍스트를 찾는 명령어이다.

            if (tempTr.name.Contains ("_body")) {                
                Target.GetComponent<Animated_Death_Combine>().Model_1 = tempTr.gameObject.GetComponent<Renderer>();
            } 
            else if (tempTr.name.Contains ("_head")|| tempTr.name.Contains ("face")) {
                Target.GetComponent<Animated_Death_Combine>().Model_2 = tempTr.gameObject.GetComponent<Renderer>();
            } 
            else if (tempTr.name.Contains ("_weap")) {                
                Target.GetComponent<Animated_Death_Combine>().Model_3 = tempTr.gameObject.GetComponent<Renderer>();
            }
            else if (tempTr.name.Contains ("_BODY")) {
                Target.GetComponent<Animated_Death_Combine>().Shadow_1 = tempTr.gameObject.GetComponent<Renderer>();
            } else if (tempTr.name.Contains ("_HEAD") || tempTr.name.Contains ("_FACE")) {                
                Target.GetComponent<Animated_Death_Combine>().Shadow_2 = tempTr.gameObject.GetComponent<Renderer>();
            }else if (tempTr.name.Contains ("_WEAP")) {                
                Target.GetComponent<Animated_Death_Combine>().Shadow_3 = tempTr.gameObject.GetComponent<Renderer>();
            }

            if (tempTr.childCount > 0)
            {
                SerchObjectsInChild(tempTr);
            }
        }
    }
}