[Unity] Enum과 추상클래스 활용 Refactoring

고현규·2024년 1월 9일
0

이전 글 "같은 종류 다른 타입 리팩토링"에서 이어진다.

Enum을 이용해서 Key 아이템을 다른 타입인지를 판단해서 구분한다.
또한 추상 클래스를 이용해서 중복되는 코드 부분을 단축시킨다.

이번 리팩토링을 통해서 Enum의 사용법과 추상클리스의 실사용을 경험하였다.

기존 클래스

public class LockObject : MonoBehaviour
{
    [SerializeField] private GameObject KeyDoor;
    [SerializeField] private AudioSource OpenDoorSound;

    private BoxCollider _doorCollider;
    private Animator _doorAnimator;

    enum Color {Blue, Green, Red };
    [SerializeField] private Color _keycolor;
    

    private void Start()
    {
        _doorCollider = KeyDoor.GetComponentInChildren<BoxCollider>();
        _doorAnimator = KeyDoor.GetComponentInChildren<Animator>();
    }


    public string GetInteractPrompt()
    {  // C
        if (Main.Player.KeyCheck.Blue == true && _keycolor == Color.Blue)
            return string.Format("Open {0} Door", _keycolor);

        else if (Main.Player.KeyCheck.Red == true && _keycolor == Color.Red)
            return string.Format("Open {0} Door", _keycolor);

        else if (Main.Player.KeyCheck.Green == true && _keycolor == Color.Green)
            return string.Format("Open {0} Door", _keycolor);

        else
            return string.Format("Need {0} Key", _keycolor);
    }

    public void OnInteract()
    {
        if (Main.Player.KeyCheck.Blue == true && _keycolor == Color.Blue)
            DoorInteraction();
        if (Main.Player.KeyCheck.Red == true && _keycolor == Color.Red)
            DoorInteraction();
        if (Main.Player.KeyCheck.Green == true && _keycolor == Color.Green)
            DoorInteraction();
    }

    public void DoorInteraction()
    {
        _doorAnimator.SetTrigger("OpenDoor");
        Main.Game.CallDoorOpen();
        Destroy(_doorCollider);

        if (!OpenDoorSound.isPlaying)
            OpenDoorSound.Play();
    }
}

1. Key의 타입이 무엇인지 판별하는 곳에서 코드가 중복된다.
2. Key를 가지고 있는지 판별하는 bool 값이 변수가 3개며, 중복된다

리팩토링 코드

public abstract class Door : MonoBehaviour, IInteractable
{
    [SerializeField] private GameObject KeyDoor;
    [SerializeField] private AudioSource OpenDoorSound;

    private BoxCollider _doorCollider;
    private Animator _doorAnimator;

    private void Start()
    {
        _doorCollider = KeyDoor.GetComponentInChildren<BoxCollider>();
        _doorAnimator = KeyDoor.GetComponentInChildren<Animator>();
    }

    public abstract string GetInteractPrompt();

    public virtual void OnInteract()
    {
        DoorInteraction();
    }

    public void DoorInteraction()
    {
        _doorAnimator.SetTrigger("OpenDoor");
        Main.Game.CallDoorOpen();
        Destroy(_doorCollider);

        if (!OpenDoorSound.isPlaying)
            OpenDoorSound.Play();
    }
}

추상 클래스로 Door를 만들어서 기본적으로 중복되는 변수 선언과 할당을 하나로 만들었다.
IIteractable로 만든 GetInteractPrompt() 와 OnInteract()를 추상클라스와 virtual로 만들었다.

중복되는 내부함수 DoorInteraction()을 사용하기 위해 OnInteract()는 virtual로 만들었고,
GetInteractPrompt는 Door 클래스를 상속받은 자식 클래스에서 모두 따로 작성하기 위해 추상메서드로 만들었다.

Player 내부에 Enum 정의하기

# 기존 함수
public class KeyCheck
{
    public ItemType KeyColor = ItemType.None;

    public bool Red { get; set; }
    public bool Blue { get; set; }
    public bool Green { get; set; }
}

기존에 3가지로 키 색깔 변수를 지정했던 것을 아래로 바꾸었다.

public enum ItemType
{
    None,
    RedKey,
    BlueKey,
    GreenKey
}

public class KeyCheck
{
    public ItemType KeyColor = ItemType.None;
}

Enum을 사용하면서 알게 된 사실은 아래와 같다

enum은 클래스와 같은 역할을 하기에 Class 내부가 아니라 바깥에 선언해주어야 한다.

자식 클래스

# 빨간 문
public class RedDoor : Door
{
    ItemType _keyColor = ItemType.RedKey;

    public override string GetInteractPrompt()
    {
        if(Main.Player.KeyCheck.KeyColor != _keyColor)
        {
            return "Need" + _keyColor;
        }
        return "Open" + _keyColor + "Door";
    }

    public override void OnInteract()
    {
        if (Main.Player.KeyCheck.KeyColor != _keyColor)
            return;

        base.OnInteract();
    }
}
# 파란 문
public class BlueDoor : Door
{
    ItemType _keyColor = ItemType.BlueKey;

    public override string GetInteractPrompt()
    {
        if (Main.Player.KeyCheck.KeyColor != _keyColor)
        {
            return "Need" + _keyColor;
        }
        return "Open" + _keyColor + "Door";
    }

    public override void OnInteract()
    {
        if (Main.Player.KeyCheck.KeyColor != _keyColor)
            return;

        base.OnInteract();
    }
}
#초록 문
public class GreenDoor : Door
{
    ItemType _keyColor = ItemType.GreenKey;


    public override string GetInteractPrompt()
    {
        if (Main.Player.KeyCheck.KeyColor != _keyColor)
        {
            return "Need" + _keyColor;
        }
        return "Open" + _keyColor + "Door";
    }

    public override void OnInteract()
    {
        if (Main.Player.KeyCheck.KeyColor != _keyColor)
            return;

        base.OnInteract();
    }
}

자식 클래스 내부에 ItemType을 선언해서 각 객체의 색을 정해주었다.
이렇게 작성하고보니 매개변수로 색깔만 정해주어도 좋았을 거라는 생각은 든다.

이렇게 전략 패턴을 이용해서 아이템 객체에 따라서 다르게 실행되는 코드를 작성할 수 있었다.

profile
게임 개발과 기획

0개의 댓글