[TIL] Unity - Find 사용 자제 이유! - day 62

뭉크의 개발·2023년 10월 13일
0

Unity - Camp

목록 보기
31/70
post-thumbnail

🐧 들어가기 앞서

Audio 작업을 진행했다!

이전에 썼던 오디오 코드를 수정하고, 업그레이드 할 예정이다.

우선 저번 프로젝트에서 오디오를 담당할 때, 막혔던 부분은

BGM을 여러개로 나누지 못했던 것, enum을 같은 클래스안에서 사용했던 것이다.

또한 함수를 사용하는 데 있어서 더 효율적인 코드가 있을지 연구하는 중이다.


🐧 오늘 배운 것

  1. 유니티에서 Find 함수가 좋지 않은 이유!

🐧 기억할 것 & 진행

Find

개념

Find 메서드는 게임 오브젝트의 이름을 통해 해당 오브젝트를 찾아주는 기능을 제공한다. 유니티의 모든 게임 오브젝트 중에서 특정 이름을 가진 오브젝트를 반환한다.

비효율성

  1. 성능 문제
    Find 메서드는 하이어라키에 있는 모든 게임 오브젝트를 탐색하므로 많은 수의 게임 오브젝트가 존재할 때, 성능 저하가 발생할 수 있다.

  2. 이름 변경 문제
    만약 찾고자 하는 게임 오브젝트의 이름이 변경되면, Find 메서드는 더 이상 해당 객체를 찾지 못한다. 즉, 코드와 게임 환경 사이 일관성이 깨질 수 있다.

  3. 중복된 이름 문제
    같은 이름을 가진 여러 오브젝트가 존재할 경우, 원하지 않는 오브젝트가 반환될 수 있다.

  • 예시
public class PlayerController : MonoBehaviour
{
    private GameObject enemy;

    void Start()
    {
        enemy = GameObject.Find("Enemy");
    }

    void Update()
    {
        if (enemy != null)
        {
        }
    }
}

대안

1. 직접 참조

  • Inspector에서 직접 필요한 컴포넌트, 게임 오브젝트를 할당하는 것이다. 대부분의 문제를 해결할 수 있다.
public class PlayerController : MonoBehaviour
{
    public GameObject enemy;

    void Update()
    {
        if (enemy != null)
        {
        }
     }
}

2. 싱글턴 패턴 사용

  • 전역 단일 인스턴스가 필요한 경우, 싱글턴 패턴을 사용할 수 있다.

3. 메시지 전달 방식

  • 특정 조건에 따라 동적으로 메시지를 호출하여 전달하는 방식이다. SendMessage, BroadcastMessage등이 있지만 권장되지 않는다.

아래는 모두 직접 참조 방식과 연관되어있다.

  • SendMessage 예시
public class PlayerController : MonoBehaviour
{
    public GameObject enemy; // Set this in the Inspector

    void Start()
    {
        if (enemy != null)
        {
            // "TakeDamage"라는 메서드를 호출하고 10을 인자로 전달.
            enemy.SendMessage("TakeDamage", 10, SendMessageOptions.DontRequireReceiver);
        }
    }
}
  • BroadcastMessage 예시
public class PlayerController : MonoBehaviour
{
    public GameObject enemies; // Set this in the Inspector

    void Start()
    {
        if (enemies != null)
        {
            // 모든 하위 Enemy에게 "TakeDamage" 메시지를 전달하고 10을 인자로 전달.
            enemies.BroadcastMessage("TakeDamage", 10, SendMessageOptions.DontRequireReceiver);
        }
     }
}
  • SendMessageUpwards 예시
public class PlayerController : MonoBehaviour
{
    public GameObject childObject; // Set this in the Inspector

    void Start()
    {
        if (childObject != null)
        {
            // 자신과 상위 객체들에게 "NotifyParent" 메시지륿 보낸다.
            childObject.SendMessageUpwards("NotifyParent", SendMessageOptions.DontRequireReceiver);
         }
     }
}

추후에 다뤄볼 계획이지만, 문자열을 이용해 호출하는 것은 비용이 많이 들기 때문에 성능 저하가 발생할 수 있다.

4. 태그 활용

  • 특정한 기능을 가진 게임 오브젝트를 그룹화하거나, 특정한 타입의 게임 오브젝트를 찾는데 사용된다.

  • Tag 사용 예시

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
        
        foreach(GameObject enemy in enemies)
        {
            Debug.Log(enemy.name);
        }
    }
}

이 역시도 성능상에 비용이 있다.

정리

'Find' 함수는 유니티 엔진 내부에서 모든 객체들 중 원하는 객체를 문자열 기반으로 검색하여 반환하는 함수다.

하지만 이 함수는 성능 저하, 이름 변경에 따른 오류, 이름 중복 등의 문제를 일으킬 수 있어 사용을 자제하는 것이 좋다.

대신 인스펙터에서 직접 참조하거나 싱글턴 패턴, 메시지 전달 방식, 태그 활용 등 다른 방법을 사용하여 객체를 관리하는 것이 더 효율적이다.


🐧 내일 할 일

오디오 기능 생각하기

0개의 댓글