오늘은 Find 함수 사용과 관련해 정리하고자 합니다.
Find 계열 함수들은 이름을 통해 해당 오브젝트를 찾아주는 기능을 제공합니다.
편리해 보여서 자주 사용할 것 같지만 대부분 사용을 지양하더군요.
왜일까요?
1.
Find 계열 함수들은 씬(Scene) 전체를 순회하면서 해당 이름을 검색하는 문자열과 비교합니다.
이 과정에서 성능적으로 문제가 발생할 수 있습니다.
2.
여러 개의 같은 이름(혹은 타입 등)의 오브젝트가 있을 경우 의도치 않은 결과가 발생 수 있습니다.
3.
컴파일 - 코드 - 에서 확인할 수 있는 게 아니라
런타임 도중에 이름이 변경되거나 변동이 생기면 오류가 나기 쉽습니다.
이러한 이유로 사용을 지양하고 있는 듯합니다.
그러면 특정 오브젝트를 찾으려면 어떻게 하는 게 좋을까요?
Find 계열의 함수를 대체 할 수 있는 5가지 방법을 소개하고자 합니다.
Find 사용을 대체 할 수 있는 방법들
1. Inpector에서 직접 할당하는 방법
public class PlayerController : MonoBehaviour
{
[SerializeField] private GameObject target;
[SerializeField] private Transform targetTransform;
[SerializeField] private Camera mainCamera;
private void Update()
{
if (target != null) {
// target 사용
}
}
}
2. 컴포넌트를 캐싱하는 방법
public class WeaponController : MonoBehaviour
{
private Animator animator;
private Rigidbody rb;
private ParticleSystem particleSystem;
private void Awake()
{
// 시작할 때 한 번만 캐싱, 이후엔 해당 변수로 재사용
animator = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
particleSystem = GetComponent<ParticleSystem>();
}
}
3. 인스턴스화 시 참조 저장하는 방법
public class ObjectSpawner : MonoBehaviour
{
[SerializeField] private GameObject prefab;
private List<GameObject> spawnedObjects = new List<GameObject>();
public GameObject SpawnObject(Vector3 position)
{
// 생성과 동시에 참조 저장
GameObject newObject = Instantiate(prefab, position, Quaternion.identity);
spawnedObjects.Add(newObject);
return newObject;
}
public void DestroyAllSpawned()
{
foreach (var obj in spawnedObjects)
{
if (obj != null)
{
Destroy(obj);
}
}
spawnedObjects.Clear();
}
}
4. 싱글톤 패턴 활용
public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
public int Score { get; private set; }
public bool IsGameOver { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
// 다른 스크립트에서 사용
// GameManager.Instance.Score 처럼 접근
}
5. 이벤트 시스템 활용
public class EventManager : MonoBehaviour
{
public static event System.Action<int> OnScoreChanged;
public static event System.Action OnGameOver;
public void UpdateScore(int newScore)
{
OnScoreChanged?.Invoke(newScore);
}
public void GameOver()
{
OnGameOver?.Invoke();
}
}
// 다른 스크립트에서 이벤트 구독
private void OnEnable()
{
EventManager.OnScoreChanged += HandleScoreChanged;
EventManager.OnGameOver += HandleGameOver;
}
private void OnDisable()
{
EventManager.OnScoreChanged -= HandleScoreChanged;
EventManager.OnGameOver -= HandleGameOver;
}
마무리
오늘은 간단하게 Find 사용에 관해 정리해 봤습니다.
이전에 학습하면서 알고 있던 내용이었는데, 면접 질문 대비하면서 이와 관련한 질문이 나오더군요.직접적으로 블로그에 쓴 적은 없는 것 같아 복습 겸 작성해 봤습니다.