스파르타코딩클럽 게임개발

오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 54일차(최종프로젝트 5일차 옵저버 패턴 사용해서 부모 오브젝트에게 정보전달하기)

코드천자문 2024. 1. 17. 02:15
반응형

옵저버 패턴을 사용해서 부모오브 젝트에게 정보를 전달하자!

왜?

 이런것을 만들게 되엇냐면.. 물건이 부숴진것을 원래 모습으로 되돌아가는 형상을 구현하고 싶어서였다.

그러기 위해선 부숴진 오브젝트가 필요했는데 부숴진 오브젝트를 다 따로 관리할수없으니 부모 오브젝트에 자식오브젝트로

만들어 두었다.

그래선 기존의 코드로는 자식오브젝트 중 하나라도 클릭 되었을때 모두가 역재생이 되는 기능이 구현되지 않으니 부모 오브젝트에 들어가는 스크립트를 따로 만들어야 했다.

그 스크립트를 만드는데 필요한것이 정보의 전달 이것을 어떻게 전달할까 고민이 많았다.

그래서 사용한 것이 바로 옵저버 패턴이다.

개요

옵저버 패턴은 객체의 상태 변화를 다른 객체들이 감시(Observe)하고, 상태 변화가 발생하면 알림을 받는 디자인 패턴이다. 이를 통해 객체 간의 결합도를 낮추고, 코드의 유지 관리성을 높일 수 있다.

아래 예시는 내가 작성했던 ReplayRecorder라는 자식오브젝트의 스크립트가 상태 변화를 감지하고, 이를 ParentObject 부모오브젝트의 스크립트에게 알리는 과정을 보여준다.

코드

// ReplayRecorder 클래스
public class ReplayRecorder : MonoBehaviour
{
    // 상태 변화를 알리는 델리게이트와 이벤트 정의
    public delegate void StateChangeHandler(ReplayRecorder sender, bool isDone, bool isClick);
    public static event StateChangeHandler OnStateChange;

    // ... (생략)

    // 상태 변화를 감지하고 이를 알림
    public void Recording(bool newIsDone, bool newIsClick)
    {
        isDone = newIsDone;
        isClick = newIsClick;
        OnStateChange?.Invoke(this, newIsDone, newIsClick); // 상태 변화 알림
    }

    // ... (생략)
}

// ParentObject 클래스
public class ParentObject : MonoBehaviour
{
    // ... (생략)

    private void Start()
    {
        // 상태 변화 이벤트에 대한 리스너 등록
        ReplayRecorder.OnStateChange += HandleStateChange;
    }

    // 상태 변화 이벤트 핸들러
    private void HandleStateChange(ReplayRecorder child, bool isDone, bool isClick)
    {
        // 상태 변화를 처리하는 로직
    }

    // ... (생략)
}

동작 설명

  1. ReplayRecorder 클래스는 Recording 메서드를 통해 자신의 상태 변화를 감지한다. Recording 메서드가 호출되면, OnStateChange 이벤트가 발생하고 이에 따른 인자들이 전달된다.
  2. ParentObject 클래스는 Start 메서드에서 OnStateChange 이벤트에 대한 리스너를 등록한다. 이 리스너는 HandleStateChange 메서드로, 상태 변화를 감지하면 호출된다.
  3. ReplayRecorder의 상태가 변하면 OnStateChange 이벤트가 발생하고, ParentObjectHandleStateChange 메서드가 호출된다. 이 메서드는 상태 변화를 처리하는 로직을 담고 있다.

이렇게 옵저버 패턴을 사용하면, ReplayRecorderParentObject와 같이 서로 다른 클래스나 객체 간에 데이터를 쉽고 효율적으로 전달할 수 있다. 이는 코드의 구조를 깔끔하게 유지하면서, 유연성과 확장성을 높이는 데 도움이 된다.

 

원래라면 GetComponentsInChildren<T>를 사용하여 자식의 컴포넌트를 불러와 사용했겠지만

최근에 김하연튜터님의 옵저버 패턴 강의를 보고 이를 적용해 보았다.

 

 

옵저버 패턴이 GetComponentsInChildren<T>보다 무엇이 좋을까?

 

결합도 감소

옵저버 패턴의 사용은 부모 객체와 자식 객체 간의 결합도를 낮추는 데 큰 도움이 된다. GetComponentsInChildren<T>를 사용할 경우, 부모 객체는 자식 객체의 구체적인 구현에 의존하게 된다. 이는 코드의 유연성을 저해하고, 확장성을 떨어뜨린다.

반면, 옵저버 패턴을 활용하면 이벤트를 발생시키는 객체와 이벤트를 수신하는 객체 간의 결합을 최소화할 수 있다. 이는 코드의 유연성과 확장성을 크게 향상시킨다.

효율성 증대

GetComponentsInChildren<T>는 자식 객체를 순회하며 특정 컴포넌트를 찾는 과정이 필요하므로, 큰 비용이 든다. 특히 자식 객체의 수가 많을 경우, 이 비용은 더욱 커진다.

반면, 옵저버 패턴은 이벤트가 발생하면 즉시 알림을 받을 수 있기 때문에 실행 시간이 짧다. 이는 특히 상태 변화가 빈번하게 일어나는 상황에서 큰 장점이 된다.

유지보수성 향상

GetComponentsInChildren<T>를 사용할 경우, 자식 객체의 구조나 컴포넌트가 변경될 때마다 부모 객체의 코드도 수정해야 할 가능성이 생긴다. 이는 유지보수를 어렵게 만든다.

하지만 옵저버 패턴을 사용하면 이벤트를 발생시키는 객체와 이벤트를 수신하는 객체를 독립적으로 수정하거나 확장할 수 있다. 이로 인해 유지보수가 쉬워진다.

결론

따라서, GetComponentsInChildren<T>보다는 옵저버 패턴을 사용하는 것이 유연성, 효율성, 유지보수성 면에서 더 우수하다. 이들 장점을 통해 복잡한 시스템을 관리하고, 코드의 품질을 높일 수 있다.

 

영상 

부숴진 유리가 원래의 위치로 돌아간다 아직 부숴지기 전의 모습으로 돌아가는 기능은 구현하지 않았다. 하지만 그부분은 그냥 프리펩 바꿔치기로.. ㅋ

 

 

 

반응형