해결된 질문
작성
·
92
·
수정됨
0
component.name에는 T 컴포넌트를 가진 게임 오브젝트의 이름이 와야 하는데, 게임 오브젝트의 이름이 아닌 컴포넌트의 이름이 옵니다. 예를 들면 FindChild<Button>이라면, component.name에 Button이 와, FindChild 함수가 계속 null만 return하는 상황입니다.
(아래에 코드 첨부)
코드 문제가 아니라 오브젝트 이름 문제였네요,,ㅠㅠ 해결했습니다
UIButton.cs
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class UIButton : MonoBehaviour
{
// 타입별로 오브젝트를 저장
Dictionary<Type, UnityEngine.Object[]> _objects = new Dictionary<Type, UnityEngine.Object[]>();
[SerializeField]
TextMeshProUGUI text;
// Button 오브젝트의 이름들을 enum으로 저장
enum Buttons
{
PointButton,
}
enum Texts
{
PointText,
ScoreText,
}
private void Start()
{
Bind<Button>(typeof(Buttons)); // enum은 Buttons인데, Button 컴포넌트를 가진 오브젝트에 매핑해주세요라는 의미
Bind<Text>(typeof(Texts));
Get<Text>((int)Texts.ScoreText).text = "Bind Test";
}
void Bind<T>(Type type) where T : UnityEngine.Object
{
// 1. 딕셔너리에 enum 요소 수만큼 빈 object 배열 넣어주기
string[] names = Enum.GetNames(type); // enum값들이 names에 string으로 담김
UnityEngine.Object[] objects = new UnityEngine.Object[names.Length];
_objects.Add(typeof(T), objects);
// 2. 실질적인 컴포넌트(오브젝트) 찾기
for (int i = 0; i < names.Length; i++)
{
objects[i] = Util.FindChild<T>(gameObject, names[i], true);
}
}
T Get<T>(int idx) where T : UnityEngine.Object
{
UnityEngine.Object[] objects = null;
if (_objects.TryGetValue(typeof(T), out objects) == false)
return null;
return objects[idx] as T;
}
int score = 0;
public void OnButtonClicked()
{
score++;
text.text = $"Point : {score}";
}
}
Util.cs
using Unity.VisualScripting;
using UnityEngine;
public class Util
{
// go는 최상위 오브젝트 / recursive는 그 자식뿐만 아니라 자식의 자식도 계속 파고들며 찾을건지 여부
public static T FindChild<T>(GameObject go, string name = null, bool recursive = false) where T : UnityEngine.Object
{
if (go == null)
return null;
if (recursive == false)
{
for (int i = 0; i < go.transform.childCount; i++)
{
Transform transform = go.transform.GetChild(i);
if (string.IsNullOrEmpty(name) || transform.name == name)
{
T component = transform.GetComponent<T>();
if (component != null)
return component;
}
}
}
else
{
foreach (T component in go.GetComponentsInChildren<T>())
{
if (string.IsNullOrEmpty(name) || component.name == name)
return component;
}
}
return null;
}
}
답변 2
0
함수의 조건을 where T : UnityEngine.Component
코드를 component.gameObject.name == name로 수정해보시기 바랍니다.
사실 굳이(?) 이름으로 찾는 경우가 없어서 누락된 것 같네요!
0
안녕하세요, 인프런 AI 인턴입니다.
현재 질문에서 제기된 문제는 Unity에서 FindChild
함수를 사용하여 게임 오브젝트의 이름을 찾고자 할 때, component.name
이 아닌, T 타입 컴포넌트의 이름이 반환되는 상황입니다. 이로 인해 함수가 예상과 달리 null
을 반환하게 되는 경우가 발생합니다.
이 문제의 원인은 component.name
을 사용할 때 발생합니다. Unity에서는 컴포넌트의 name
속성이 해당 컴포넌트를 포함하고 있는 게임 오브젝트의 이름을 가져오는데, 반대로 사용하는 경우엔 컴포넌트 이름을 가져옵니다. 따라서, component.name
을 사용하기보다 transform.name
을 좀 더 적합하게 사용해야 하는 경우입니다. 이는 FindChild
메서드의 반복문에서 transform.name
을 사용하여 이름을 비교하도록 변경할 필요가 있습니다.
아래는 같은 의문점에 대한 유사한 질문이 오간 사례입니다. 이를 참고하시면 도움이 될 수 있습니다:
Util.FindChild<T>(gameObject, names[i], true)와 관련하여…
김지수님의 질문에 대해, “디버깅한 장면에서 _objects 딕셔너리의 Value 값이 \“PointButton{Unity.Engine.UI.Button}\“로 되어 있는 건 사실은 Button Component를 return 했지만 걔는 PointButton꺼야 라는 뜻인가요”에 대한 답변 등이 포함되어 있습니다.
FindChild 질문
dongdong00님의 질문에서 “이 button 컴포넌트를 찾는 건데 컴포넌트의 .name은 붙어있는gameObject의 이름을 따라가니까 PointButton으로 찾을 수 있던거라고 이해하면 될까요?“에 대한 답변 등을 확인할 수 있습니다.
위의 링크들을 참조하여 문제를 보다 이해하고 해결책을 찾으시길 바랍니다. 코드를 수정하고자 할 때, component.name
대신 transform.name
을 사용해 보는 일이 가장 직접적인 식별 방법입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.