Unity/Unity Study

[Unity] 쿠키런 모작 팀 프로젝트 중, Item 1 - 기본 아이템 구현 (트러블)

Jee-U 2025. 2. 26. 21:01

 

사실 아이템은 예전부터 해보고싶었던 부분이지만 지금의 내가 맡기엔 어려운 부분이라고 생각하여 그나마 자신있는 UI를 하겠다고 얘기드렸지만 해보고싶은걸 하시라며 아이템 담당으로 배정해주신 팀원분들.. 믿고

맡겨주셨는데 내가 다 우당탕탕 망쳐버릴까봐 무섭다, 그치만 맡은거 일단 해내야지.

 

내가 구상했던건 enum으로 아이템 종류를 관리, OnTriggerEnter2D로 충돌했을 때 아이템 효과를 적용, Switch/Case문으로 아이템 종류에 따른 효과를 적용할 수 있게 하려고 하였다.

 

일단 필수로 해야하는 아이템 3가지 먼저 구상하고 시간이 있을 경우 다른걸 구현하자 생각했던 상태로 3가지 아이템은 다음과 같다.

  • 점수가 추가하는 젤리
  • 체력이 증가하는 포션
  • 모든 장애물을 파괴하고 일시로 무적이 될수 있는 아이템

코드 작성 전 머릿속에 구상한거 일단 메모해둔 것

뭔가 하기전에 머릿속에 있는걸 간단하게 그려두거나 정리해두고 시작하는 버릇으로 인해 써두었던 메모

public class Item : MonoBehaviour
{
    public Player player;

    public enum ItemType
    {
        Score,
        Heal,
        Shield
    }
    
    public ItemType itemType;
    // 값은 임시, 나중에 다르게 할 경우 삭제하고 값 입력하기
    public int value = 10;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        player = collision.GetComponent<PlayerController>();
        if (player != null)
        {
            ApplyEffect(player);
            Destroy(gameObject);
        }
    }
    
        public virtual void ApplyEffect(Player player)
    {
        switch (itemType)
        {
            case ItemType.Score:
                // 스코어 경로가 게임매니저라면 게임매니저(GameManager.Instance)로 바꿔주기
                player.AddScore(value);
                break;

            case ItemType.Heal:
                player.Heal(value);
                break;

            case ItemType.Shield:
                player.Shield(5f); // 5초간 무적
                break;
        }
    }
 }

일단 머릿속에 있는 부분을 코드로 작성하였을 땐 위와 같았다.

AddScore(점수 추가)부분은 GameManager, Heal과 Shield(무적상태 등)은 체력과 장애물과 충돌했을 때 발생하는 무적부분과도 관련이 있어 Player 클래스에 넣어야겠다고 생각하고 작성하였다.

 

 

 

근데 이런형식으로 해도 되는지 확신이 안서 팀원분들께 여쭤보기도 하고 같이 의논해보았는데

ItemEffect 말고 ApplyEffect와 같은 메서드명이 좋을듯 하며  OnTrigger과 Destroy 전에 ApplyEffect가 먼저 실행할 수 있게 다만 ApplyEffect를 Override로 하여 나누었으면 좋겠다고 하셨다.

근데 나는 아직 Override를 완전히 이해하지 못한 상태.. 그래서 혼자 Overrride에 대해 공부하고 따로 다른분께 조언도 구하고 하여 아래와 같이 작성했다.

public class Item : MonoBehaviour
{
    public Player player;

    public enum ItemType
    {
        Score,
        Heal,
        Shield
    }

    public ItemType itemType;
    // 값은 임시, 나중에 다르게 할 경우 삭제하고 값 입력하기
    public int value = 10;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        //player = collision.GetComponent<PlayerController>();
        if (player != null)
        {
            ApplyEffect(player);
            Destroy(gameObject);
        }
    }

    public virtual void ApplyEffect(Player player)
    {
        switch (itemType)
        {
            case ItemType.Score:
                GameScore.Instance.AddScore(value);
                break;

            case ItemType.Heal:
                player.Heal(value);
                break;

            case ItemType.Shield:
                player.Shield(5f); // 5초
                break;
        }
    }




    public class Score : Item
    {
        public override void ApplyEffect(Player player)
        {
			base.ApplyEffect(player);
			player.AddScore(value);
        }
    }

    public class Potion : Item
    {
        public override void ApplyEffect(Player player)
        {
			base.ApplyEffect(player);
			player.Heal(value);
        }
    }
}

 

- Score, Potion은 각 자식 클래스별 스크립트를 따로 만들어주어야 각 게임오브젝트/프리펩에 컴포넌트로 적용 가능하기 때문에 따로 작성해주었음.

 

일단 회복물약과 스코어를 늘려주는 아이템은 값을 입력해주어야하니 value로 두기에도 뭐했고, 값을 종류에 따라(크기가 크면 더 많은 회복과 점수를, 작으면 작은 회복과 점수를 주게끔) 변경해주고 싶었는데 고정값으로만 해야하나 여러 고민을 하였다.

 

그러다 몇가지 깨달음이 생겼는데..

  • override를 사용함으로써 switch/case문은 사용할 필요가 없게됨
  • 각 자식 클래스별 스크립트를 따로 만들어주어야 각 게임오브젝트/프리펩에 컴포넌트로 적용 가능
  • 각 효과별로 스크립트를 따로 만들어주기 때문데 enum또한 사용할 필요는 딱히 없음
  • [SerializeField] 기능을 이용하면 오브젝트 개별로 값을 줄 수 있음

 

그리고 제일 중요한 Override의 기능을 쓰고자 하는건 Item의 ApplyEffect 메서드를 두고 다른 포션, 젤리 등의 아이템을 재정의해서 사용하고자 하는것이다.

요약하자면

  • 부모(Item) : ApllyEffect()를 정의하지만 비워둠
  • 자식(Coin, Potion 등) : ApllyEffect()를 각 아이템의 효과에 맞게 오버라이드 해서 구현

공통된 구조(캐릭터와 아이템이 닿으면 아이템은 파괴 등, 아이템이라는 구조)는 유지하면서, 아이템마다 다른 효과를 줄 수 있게 하고자 하는것이 목적이다.

 

수정된 코드는 여기에