내일배움캠프/프로젝트

팀 프로젝트 - 아이템 기반

서보훈 2024. 12. 13. 20:56

게임내에서 사용될 아이템의 기반을 만들어주었습니다.

기본 틀은 모든 아이템이 가질 정보를 저장하는 ItemBase를 최상단 추상 클래스로 구현한 뒤,

필드에 드랍되어 있거나 플레이어가 손에 들고있을 아이템의 오브젝트를 ItemObject로, 아이템 사용으로 인해 생성되는 투사체용으로 ItemProjectile 을 만들어주었습니다.

 

또한 ItemObject의 경우 추상클래스로 사용되며, 인터페이스인 IUseable을 통해 아이템 사용시 효과를 구현하게됩니다.

이때, 사용시 발생하는 효과 메서드는 추상클래스로 구현하여 아이템의 고유 사용효과를 구현하도록 만들어주었습니다.

더보기

기반 ItemBase

public enum ItemState
{
    None,
    Dropped,
    Holding
}

public abstract class ItemBase : MonoBehaviour
{
    public ItemData itemData;
    protected ItemState state;

    protected Collider trigger;

    private void Awake()
    {
        trigger = GetComponent<Collider>();
    }
}

필드, 사용에 사용될 아이템 클래스 

※ IInteractive 등의 인터페이스를 사용하여 드랍 아이템의 상호작용 기능을 만들어주어야합니다.

public abstract class ItemObject : ItemBase, IUseItem
{
    //아이템 상태 설정, 들고있을때, 땅에 있을때
    public void SetState(ItemState itemState)
    {
        state = itemState;

        if (state == ItemState.Dropped)
        {
            trigger.enabled = true;
        }
        else
        {
            trigger.enabled = false;
        }
    }

    //아이템 사용시 호출하는 메서드
    public void UseItem()
    {
        if (state == ItemState.Dropped) return;

        ItemEffect();
    }

    //아이템 상호작용 메서드(획득)
    public void OnInteractive()
    {
        if (state == ItemState.Holding) return;
    }

    //실제 아이템 효과처리를 하는 추상메서드
    protected abstract void ItemEffect();
}

 

사용 아이템중 하나

(제가 설계한 내용은 아니기 때문에 별도의 설명은 없이 넘어가겠습니다. ItemEffect에서 효과 처리를 한다는점만 알아주시면 됩니다.)

public class HidePaperTalisman : ItemObject
{
    public Ghost ghost;
    public GhostStateMachine stateMachine;

    protected override void ItemEffect()
    {
        CoroutineManager.Instance.StartCoroutine(HidePlayer());
    }

    private IEnumerator HidePlayer()
    {

        float endDuration = Time.time + itemData.ItemDuration;
        
        while (Time.time < endDuration)
        {
            if(stateMachine.currentState == stateMachine.GhostChasingState && stateMachine.currentState == stateMachine.GhostAttackState) stateMachine.ChangeState(stateMachine.GhostIdleState);   // 추격상태와 공격 상태라면 정지상태로 그외에는 순찰상태로 변환
            
             else stateMachine.ChangeState(stateMachine.GhostPatrolState);
            ghost.isFindPlayer = false;
        }
        ghost.isFindPlayer = true;
        yield return null;
        
    }
}

 

투척 아이템

투척계열 아이템은 사용 효과가 오브젝트를 날리는 효과로, 모두 동일하기 때문에 이 클래스를 사용하여 구현하게됩니다.

public class ThrowItemObject : ItemObject
{
    [SerializeField] private float throwPower;
    //던져질 아이템 프리팹
    [SerializeField] private ItemProjectile throwedItem;

    //아이템 던지기
    protected override void ItemEffect()
    {
        ItemProjectile item = Instantiate(throwedItem, transform.position, transform.rotation);
        item.OnThrowed(throwPower);
    }
}

 

퍼즐용 아이템

상호작용시 효과를 작성해주어야합니다. 물론, 맞지 않는 아이템을 사용했을때의 예외처리가 필요합니다.

//퍼즐용 상호작용 아이템 클래스
public class PuzzleItem : ItemObject
{
    protected override void ItemEffect()
    {
        
    }
}

 

아이템 투사체

투척 아이템 사용시 이 클래스의 자식 클래스가 붙은 프리팹이 생성됩니다.

또한, 바닦에 닿았을때 효과는 아이템마다 달라야하기 때문에, 해당 부분은 추상메서드로 구현해주었습니다.

/// <summary>
/// 투사체용 클래스, 아이템 사용시 이 클래스가 붙은 오브젝트 생성
/// </summary>
public abstract class ItemProjectile : ItemBase
{
    [SerializeField] private LayerMask collisionLayer;

    private Rigidbody rb;

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void OnTriggerEnter(Collider other)
    {
        //충돌 가능 레이어가 아니면 리턴
        if (other.gameObject.layer != collisionLayer) return;

        ItemEffect();
    }

    //던지기
    public void OnThrowed(float power)
    {
        rb.velocity = Vector3.forward * power;
    }

    //땅에 떨어지면 작동할 아이템 효과
    protected abstract void ItemEffect();
}