게임 아이템 관리하기

Tom·2024년 10월 11일
1
post-custom-banner

아이템은 RPG의 알파이자 오메가이다. 더 위의 목표를 달성하기 위해 아이템이 필요하고, 그 목표에 대한 동기부여를 제시하는 것이 바로 그 목표에서 얻을 수 있는 아이템이니까. 아이템과 목표가 상호보완적인 작용을 한다고 볼 수 있음. 이것이 루프가 되어 아이템을 얻기 위해 목표를 달성하고, 목표를 달성하기 위해 아이템을 얻는 과정이 RPG에서 대부분을 차지한다.
그래서 장기간 운영된 게임들을 보면 아이템 종류나 갯수가 굉장히 많다. 수백개를 넘어 수천개도 우습게 넘기는 게임들이 있음. 이렇게 많은 아이템을 한땀한땀 어떻게 다 만들었을까? 또 관리는 어떻게 함? 머리가 지끈지끈하다.

근데 결국 아이템도 데이터덩어리임

그래도 대부분 RPG 게임의 아이템을 보면 정형화된 문법이 있다. 착용 제한 레벨이라던가, 장착하면 오르는 능력치라던가. 이런건 당연하게 데이터로 관리가 가능하시겠다.

using UnityEngine;

public enum ItemType
{
    cape
}
public enum RequireClass
{
    Begineer, Warrier, Magician, BowMan, Theif, Pirate, All
}
public class Item 
{
    public string name = "메이플 망토";
    public bool isTradable = false;
    public Sprite itemImage;
    public int requireLevel = 70;
    public RequireClass requireClass = RequireClass.All;
    public ItemType type = ItemType.cape;
    public int armorPoint = 23;
    public int moveSpeed = 10;
    public int jumpForce = 5;
    public int upgradeLimit = 5;
}

위에 나온 아이템은 메이플스토리에서 얻을 수 있는 "메이플 망토"다. 굉장히 단순해보이는 아이템인데, 데이터로 표현해보면 아마 저런식으로 나올듯. 그럼 이제 저런 아이템을 머리, 갑옷, 무기, 신발별로 수없이 찍어내야한다. 아이템을 이렇게 엔진상에서 만들고 수정하려면 최소 변수와 타입에 대한 지식이 있는 사람이어야됨. 또 이런식으로 내부에 저장되어 있는 아이템 정보는 나중에 수치 조정등 소소한 변경사항이 있을 때에도 항상 엔진을 켜서 변경해야한다는 단점이 있다. 근데 저는 나중에도 편하게 유지보수 하고싶은데요?

그럼 스프레드시트를 쓰쇼

이름교환가능이미지레벨제한직업제한부위방어력이동속도점프력업그레이드 횟수
메이플 망토0"경로"706 0231055

그럼 데이터를 그냥 스프레드시트에 저장한다음에 불러와서 생성하면 된다. 나중에 아이템이 추가되면? 스프레드시트에 한 줄 추가해주면 됨. 아이템에 변경사항이 생기면? 스프레드시트에서 바꿔주면 됨. 관리하기 편한 방식의 데이터로 들고 다니다가 플레이 시점에만 적절하게 불러와주면 된다.

아이템에 특수한 효과가 있었으면 좋겠어요

단순히 스텟을 올려주는 게 아니라 장착하면 특별한 효과가 있는 아이템들도 있다. 어떤 무기는 장착하면 공격시 적에게 독 효과를 주고, 어떤 방어구는 맞을 때 적에게 반사 데미지를 준다. 이런건 데이터로 관리하기 어려울 듯 싶다. 이건 따로 빼서 관리하는 방법을 사용해봤다. 우선 아이템 효과들만 담아놓을 ItemEffect를 간단하게 만들었음.

using System;
using System.Collections.Generic;
using UnityEngine;

public class ItemEffect
{
  public Dictionary<string, Action<Player>> nameEffectPair =
      new Dictionary<string, Action<Player>>();

  public ItemEffect()
  {
      nameEffectPair["메이플망토"] = MapleCapeEffect;
  }

  private void MapleCapeEffect(Player player)
  {
      Debug.Log($"{player.name}은(는) 날아올랏다!");
  }
}

아이템의 이름으로 효과를 매핑하여 같은 이름의 모든 아이템이 같은 효과를 공유할 수 있게 했다. 그리고 플레이어에 메이플망토를 장착했음.

using System;
using UnityEngine;

public class Player : MonoBehaviour
{
  public string name = "메이플용사";
  private Action<Player> onAttack;
  private Item equippedItem;

  private void Awake()
  {
      ItemEffect equippedEffect = new ItemEffect();

      equippedItem = new Item()
      {
          name = "메이플망토"
      };

      onAttack += equippedEffect.nameEffectPair[equippedItem.name];
  }

  private void Update()
  {
      if(Input.GetKeyUp(KeyCode.Space))
      {
          Attack(this);
      }
  }

  private void Attack(Player player)
  {
      onAttack?.Invoke(player);
  }
}

근데 이럴거면 애초에 아이템에 Action을 미리 만들어두고 데이터를 불러올 때 담아주기만 하면 확실히 아이템에 효과를 담아둘 수 있어서 더 직관적이고 일관적으로 관리가 가능할 것 같다. 거기에만 [NonSerialized] 달아주면 될 듯?
아무튼 그다음에 실행해서 스페이스바를 눌러보면
공격할 때마다 하늘로 날아오르는 용사가 되었다.

profile
여기 글은 보통 틀린 경우가 많음
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 10월 30일

아이템의 효과 또한 데이터로 관리되긴 합니다. 재밌게 잘 봤어요 ~

답글 달기