[C#, Unity] 확장 메서드 (Extension Method)

alsry._.112·2024년 1월 26일

c#

목록 보기
4/5
post-thumbnail

Extendion Method

1. 확장 메서드란

확장 메서드는 말 그대로
기존 클래스의 기능을 확장하는 기능이다.

클래스의 외부에서 클래스의 메서드처럼 사용할 수 있는, 새로운 메서드를 만들 수 있는 기능이다.

물론 이미 만들어져 있는 클래스 이외에도 자신이 추가한 사용자 정의 클래스에서도 새롭게 확장 메서드를 만들 수 있다.

1. 확장 메서드를 만드는 법

public static class Extension
{
    public static RectTransform rectTransform(this GameObject gameObject)
    {
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        if (rectTransform == null)
        {
            Debug.LogWarning($"The GameObject '{gameObject.name}' does not have a RectTransform component.");
        }
        return rectTransform;
    }

    public static Tweener DOAnchorPos(this GameObject gameObject, Vector2 endValue, float duration)
    {
        RectTransform rectTransform = gameObject.rectTransform();
        if (rectTransform != null)
        {
            return rectTransform.DOAnchorPos(endValue, duration);
        }

        return gameObject.transform.DOMove(endValue, duration);
    }
}

확장 메서드를 만들기 위해서는 아래 3가지를 기억하면 된다.

  1. static class
  2. static method
  3. 첫 번째 매개변수에 this 키워드

우선, 확장 메서드를 정의할 클래스를 static으로 해주고,
확장 메서드또한 static으로 해준다.

그 후 확장 메서드의 첫번째 매개변수로

확장 메서드를 사용할 클래스를 넣어주게 되면,
해당 클래스의 인스턴스로 바로 함수를 호출할 수 있다.

이렇게 하여주면

원래라면
RectTransform형 변수를 선언하여 참조 후 사용하여야 했던 rectTransform과 rectTransform의 함수인 DOAnchorPos를
gameObject.DOAnchorPos를 통해 자동으로 gameObject에서 RectTransform형을 참조하여 사용 할 수 있게 된다.

좀 더 최적화

하지만 위의 코드를 보면 알 수 있듯 DOAnchorPos나 gameObject.rectTransform() 를 할때 마다 GetComponent를 하여 컴포넌트의 검색과 할당이 수행되므로 호출 빈도가 높은 경우 성능에 영향을 줄 수 있다.
때문에 필자는 RectTransform을 Dictionary에 저장하여 캐시하였다.

// RectTransform 참조를 저장하는 딕셔너리
// static으로 선언하여 프로그램이 시작할 때 한번만 메모리에 할당 되게 함. 또한 static 이므로 모든 인스턴스에서 데이터를 공유함.
// readonly를 통해 재할당이 불가하도록함 = 딕셔너리가 프로그램 실행 도중 변경되지 않음을 의미
    private static readonly Dictionary<GameObject, RectTransform> _rectTransformDic = new Dictionary<GameObject, RectTransform>();

    public static RectTransform rectTransform(this GameObject gameObject)
    {
        // 캐시된 RectTransform이 있는지 확인하고 반환
        if (_rectTransformDic.TryGetValue(gameObject, out RectTransform cachedRectTransform))
        {
            return cachedRectTransform;
        }

        // 캐시된 RectTransform이 없는 경우 GetComponent로 찾아서 캐시하고 반환
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        _rectTransformDic.Add(gameObject, rectTransform);
        return rectTransform;
    }

    public static Tweener DOAnchorPos(this GameObject gameObject, Vector2 endValue, float duration)
    {
        RectTransform rectTransform = gameObject.rectTransform();
        if (rectTransform != null)
        {
            return rectTransform.DOAnchorPos(endValue, duration);
        }

        // rectTransfor을 쓰는 오브젝트가 아니면, 그냥 DOMove로 이동
        return gameObject.transform.DOMove(endValue, duration);
    }
profile
소통해요

1개의 댓글

comment-user-thumbnail
2024년 1월 29일

몰랐던 내용 공유 감사합니다 :)

답글 달기