캐릭터의 손에 무기를 배치하려면 보통 손 뼈대를 찾아 그 아래에 해당 무기 오브젝트를 배치한다.

하지만 손 뼈대 위치는 뼈대의 최하위 자식으로 위치하여 많은 캐릭터와 무기를 일일이 처리하려면 번거로움

스크린샷 2025-05-02 222438.png

무기를 배치할 손 뼈대를 찾아 하위에 배치하는 스크립트를 구현

  1. 캐릭터(Parent Object), 손 뼈대(Child Name), 무기(Weapon Prefab)를 각각 할당
  2. 캐릭터의 자식 오브젝트 중 입력한 손 뼈대의 이름이 있는지 탐색
  3. 해당 손 뼈대에 자식으로 무기를 배치

스크린샷 2025-05-02 225327.png

다음과 같이 캐릭터 하위에 Child Name과 같은 이름을 찾아 자식으로 무기를 배치된다.

스크린샷 2025-05-03 151337.png

무기의 Transform은 따로 수정해야 된다.

스크린샷 2025-05-03 150950.png

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

/// <summary>
/// A(캐릭터)의 특정 자식(손 뼈대)을 찾아 아래에 B(무기)를 배치하는 스크립트
/// </summary>
public class WeaponMountManager : MonoBehaviour
{
    [Header("Settings")]
    public Transform parentObject;  // 무기를 넣을 부모 오브젝트
    public string childName;        // 자식 오브젝트 이름
    public GameObject weaponPrefab; // 할당할 무기 프리팹

    /// <summary>
    /// Inspector의 Mount 버튼을 누르면 호출
    /// 1. 입력 값 유효성 검사
    /// 2. 재귀 탐색으로 childName에 해당하는 Transform 찾기
    /// 3. Prefab 인스턴스화 > Undo 지원
    /// 4. target 아래에 무기 마운트
    /// </summary>
    public void MountWeapon()
    {
        // 1. 필수 필드 할당 여부 확인
        if (parentObject == null)
        {
            Debug.LogError("Parent Object가 할당되지 않음");
            return;
        }

        if (string.IsNullOrEmpty(childName))
        {
            Debug.LogError("Child Name이 비어 있음");
            return;
        }

        if (weaponPrefab == null)
        {
            Debug.LogError("Weapon Prefab이 할당되지 않음");
            return;
        }

        // 2. 부모 오브젝트 아래에서 childName과 일치하는 Transform 재귀 탐색
        Transform target = FindChildRecursive(parentObject, childName);
        if (target == null)
        {
            Debug.LogError($"'{parentObject.name}' 아래에 '{childName}' 자식이 존재하지 않음");
            return;
        }

        GameObject instance;
#if UNITY_EDITOR
        // 에디터 = PrefabUtility로 인스턴스화 + Undo 기록
        instance = (GameObject)PrefabUtility.InstantiatePrefab(weaponPrefab, parentObject.gameObject.scene);
        Undo.RegisterCreatedObjectUndo(instance, "Mount Weapon");
#else
        // 런타임 = 일반 Instantiate 사용
        instance = Instantiate(weaponPrefab);
#endif

        // 3. target Transform의 자식으로 붙이고 위치/회전 초기화
        instance.transform.SetParent(target, false);
        instance.transform.localPosition = Vector3.zero;
        instance.transform.localRotation = Quaternion.identity;

        // 4. 마운트 완료 로그
        Debug.Log($"'{target.name}' 아래에 무기를 마운트 완료");
    }

    /// <summary>
    /// 모든 자식들 중 childName과 일치하는 Transform을 찾아 반환
    /// </summary>
    Transform FindChildRecursive(Transform parent, string name)
    {
        foreach (Transform child in parent)
        {
            if (child.name == name)
            {
                return child;
            }

            Transform found = FindChildRecursive(child, name);
            if (found != null)
            {
                return found;
            }
        }
        return null;
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(WeaponMountManager))]
public class WeaponMountManagerEditor : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
        EditorGUILayout.Space();

        if (GUILayout.Button("Mount"))
        {
            (target as WeaponMountManager).MountWeapon();
        }
    }
}
#endif