11/7 TIL 디자인패턴 및 터레인

Cheorii·2024년 11월 7일

오늘 배운것

  • 디자인패턴
    - S.O.L.I.D 원칙
    - StateMachine
    - Observer Pattern
  • Terrain (터레인)
    - 졸업작품 할때 학교 지형을 제작하느라 엄청 많이 써봐서 이 부분은 정확히 머리속에 기억하기에, 생략하겠습니다.
    - 터레인 작업할 때, 빠르게 움직이고 싶으면 이동 배속 최대로 해두고, Shift누르고 움직이면 빠르게 움직인다.
    • 터레인은 타일 텍스처, 나무 프리팹 등 있으면 마구잡이로 깔 수 있음.(터레인 콜라이더에 enable collider를 사용하면 나무에도 콜라이더를 설정할 수 있다.)
  • LOD

디자인패턴

https://unity.com/kr/resources/level-up-your-code-with-game-programming-patterns

유니티 공식 문서를 참고


S.O.L.I.D 원칙

단일 책임 원칙 (Single Responsibility Principle)

  • 객체지향적 설계를 할때는 응집도를 높게하되, 결합도는 낮게 설계
    • 응집도 : 한 프로그램의 요소가 얼마나 뭉쳐있는가?
    • 결합도 : 프로그램 구송 요소들이 서로 얼마나 의존적인가?
  • 여러 객체들이 하나의 책임만 갖도록 분배하면, 시스템에 변화가 생겨도 그 영향을 최소화 할 수 있어 SRP 원칙을 따르는 것이 좋다

개방 폐쇄 원칙 (Open-Closed Principle)

  • 확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이어야 한다는 의미

리스코프 치환 원칙 (Liskov Substitution Principle)

  • 자식 클래스는 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행

인터페이스 분리 원칙 (Interface Segregation Principle)

  • SRP는 객체의 단일 책임을 뜻한다면, ISP는 인터페이스의 단일 책임

의존성 역전 원칙 (Dependency Inversion Principle)

  • 이 때 객체들은 나름대로의 원칙을 갖고 정보를 주고 받아야 한다는 설계 원칙

LOD(Level of Detail)

  • 거리에 따라 오브젝트의 정밀도를 조절


오브젝트 안에 세개의 자식이 있음.


거리에 따라 정밀하게 보이냐, 안보이냐 구분 가능

StateMachine, Observer Pattern

StateMachine


using UnityEngine;

public interface IState
{
    public void Enter();
    public void Exit();
    public void Execute();
}
using System;
using System.ComponentModel.Design.Serialization;
using Unity.IO.LowLevel.Unsafe;
using UnityEngine;

// 상태패턴을 적용하는 클래스
public class StateMachine
{
    public IState CurrentState { get; private set; }
    PlayerController player;

    // 상태패턴, 다양한 상태를 정의
    public IdleState idleState;
    public RunState runState;
    public AttackState attackState;
    public SpinState spinState;
    public DeadState deadState;

    //옵저버 패턴, 상태 변경 시 알림을 위한 이벤트
    public event Action<IState> stateChanged;   // Action<IStat>파라미터로IState타입을 건네주는 event
   
    public StateMachine(PlayerController player)
    {
        this.player = player;

        // 상태 패턴, 각 상태를 개별적으로 초기화
        idleState = new IdleState(player);
        runState = new RunState(player);
        attackState = new AttackState(player);
        deadState = new DeadState(player);
        spinState = new SpinState(player);
    }

    // 초기 상태 설정
    public void Initialize(IState state)
    {
        CurrentState = state;
        state.Enter();

        // 옵저버 패턴, 초기 상태 설정 시 옵저버(StateDisplayer)에게 알림
        stateChanged?.Invoke(state);
    }

    // 상태 전환 메서드
    public void TransitionTo(IState nextState)
    {
        //상태 패턴, 현재 상태 종료 및 새로운 상태로 전환
        CurrentState.Exit();
        CurrentState = nextState;
        CurrentState.Enter();

       // 옵저버 패턴, 상태 변경시 옵저버(StateDisplayer)에게 알림
        stateChanged?.Invoke(CurrentState); // stateChanged가 null이 아닐 때만, Inovke()호출
    }

    public void Execute()
    {
        CurrentState.Execute();
    }
}

Observer Pattern

유니티, C# 에서의 델리게이트와 같다. 델리게이트가 곧 이 옵저버 패턴인 것이다. 델리게이트 사용하면 옵저버 객체들을 리스트로 관리할 필요가 없다

상태머신과 옵저버 패턴은 스크립트에 주석을 달았음.

<옵저버 패턴>
using TMPro;
using UnityEngine;

public class StateDisplayer : MonoBehaviour
{
    public TextMeshPro stateLabel;
    PlayerController player;

    private void Awake()
    {
        player = GetComponent<PlayerController>();
    }

    private void OnEnable()
    {
        // 옵저버 패턴, 상태가 변경되면 옵저버에 현재 상태 전달
        player.stateMachine.stateChanged += OnStateChanged;
    }

    private void OnDisable()
    {
        // 옵저버 패턴, 상태변경 옵저버 해제
        player.stateMachine.stateChanged -= OnStateChanged;
    }

    // 옵저버패턴, 상태변경시 호출되는 메서드
    void OnStateChanged(IState state)
    {
        // 현재 상태 이름을 UI에 표시
        stateLabel.text = state.GetType().Name;
    }
}
using TMPro;
using UnityEngine;

public class StateDisplayer : MonoBehaviour
{
    public TextMeshPro stateLabel;
    PlayerController player;

    private void Awake()
    {
        player = GetComponent<PlayerController>();
    }

    private void OnEnable()
    {
        // 옵저버 패턴, 상태가 변경되면 옵저버에 현재 상태 전달
        player.stateMachine.stateChanged += OnStateChanged;
    }

    private void OnDisable()
    {
        // 옵저버 패턴, 상태변경 옵저버 해제
        player.stateMachine.stateChanged -= OnStateChanged;
    }

    // 옵저버패턴, 상태변경시 호출되는 메서드
    void OnStateChanged(IState state)
    {
        // 현재 상태 이름을 UI에 표시
        stateLabel.text = state.GetType().Name;
    }
}

프로젝트로 디자인패턴을 공부하니 기존에 이론을 알고 있었지만, 그 이론이 체감이 되니 이해가 빠르게 되는 느낌이다.

profile
코딩테스트는 진짜 못하겠어요 ㅠㅠ

0개의 댓글