이번 글에서는 몬스터 사냥, 상자 열기, 스테이지 클리어 보상 등 거의 모든 게임에서 필요한 아이템 드랍을 ScriptableObject 를 이용해 구현하는 방법에 대해 알아보도록 하겠습니다.
▶ Item 정의
ScriptableObject 를 이용해 다음과 같이 Item 정보를 정의해 줍니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class SOItem : ScriptableObject
{
public string itemName;
public int level;
[System.Serializable]
public struct STAT
{
public string name;
public int value;
}
public List<STAT> stats = new List<STAT>();
public int maxStack;
public int price;
public Sprite icon;
public Transform prefab;
[Multiline]
public string description;
}
여기서 prefab 은 몬스터등을 잡고 난 후 몬스터가 죽은 자리에 떨어진 아이템을 표시할 때 사용할 prefab을 연결하면 됩니다.
여기서는 Prefab 과 Icon 에 아무것도 연결하지 않았지만 실제 사용할 땐 연결해 주셔야 합니다. Icon 은 인벤토리와 같이 아이템을 아이콘 형태로 보여줄 때 사용하면 됩니다.
▶ Item Drop Table 만들기
ScriptableObject 를 이용한 Item Drop Table 은 다음과 같이 만들 수 있습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
[CreateAssetMenu]
public class SOItemDropTable : ScriptableObject
{
[System.Serializable]
public class Items
{
public SOItem item;
public int weight;
}
public List<Items> items = new List<Items>();
protected SOItem PickItem()
{
int sum = 0;
foreach (var item in items)
{
sum += item.weight;
}
var rnd = Random.Range(0, sum);
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
if (item.weight > rnd) return items[i].item;
else rnd -= item.weight;
}
return null;
}
public void ItemDrop(Vector3 pos)
{
var item = PickItem();
if (item == null) return;
Instantiate(item.prefab, pos, Quaternion.identity);
}
}
이 코드를 이용해 위에서 만든 RedPotion 과 ShortSword 의 Item drop table 을 다음과 같이 만들 수 있습니다.
이 코드에서 weight 는 아이템이 drop 될 확률의 가중치입니다. None 은 아이템을 드랍하지 않는 것입니다. 여기서는 아이템이 나오지 않을 확률이 50%, RedPotion 이 나올 확률이 33.3%, ShortSword 가 나올 확률이 16.6% 가 됩니다.
▶ SOMonster에 연결하기
SOMonster 는 이전 글에서 작성한 것을 사용할 것입니다.
2023.04.24 - [게임 프로그래밍/유니티 활용] - [유니티 활용] ScriptableObject를 이용한 Data 관리 예제 - 몬스터
SOMonster 에 다음과 같이 ItemDropTable 을 추가하도록 하겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class SOMonster : ScriptableObject
{
public int str; // strenth / 힘
public int dex; // dexterity / 민첩
public int con; // Constitution / 생명력
public SOItemDropTable itemDropTable;
}
위와같이 코드를 수정하고 다음과 같이 위에서 만든 ItemDropTable 인 IDT_Slime 을 SOMonster 로 만든 Slime 에 연결해 줍니다.
▶ Item Drop 코드
아래의 코드는 이전 글에서 만든 Slime 스크립트에 GetHit 함수를 추가하고 몬스터의 체력이 0 이하가 되면 Item Drop Table 을 이용해 선택된 아이템을 드랍하는 코드가 추가된 것입니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Slime : MonoBehaviour
{
public SOMonster soMon;
public int level;
[HideInInspector]
public int hp;
[HideInInspector]
public int dmg;
float attackDelay;
// Start is called before the first frame update
void Start()
{
hp = level * soMon.con;
dmg = level * soMon.str;
attackDelay = 1f / ((soMon.dex + level) * 0.5f);
}
public int GetHit(int d)
{
hp -= d;
if (hp <= 0)
{
// 몬스터가 죽으면 Item Drop Table 을 이용해 아이템 드랍
soMon.itemDropTable.ItemDrop(transform.position);
}
return hp;
}
}
'게임 프로그래밍 > 유니티 활용' 카테고리의 다른 글
[유니티 활용] 비쥬얼 스크립팅 (Visual Scripting) 맛보기 (1) | 2023.04.28 |
---|---|
[유니티 활용] Animator 를 이용한 애니메이션 속도 조절 (2) | 2023.04.26 |
[유니티 활용] ScriptableObject를 이용한 Data 관리 예제 - 몬스터 (0) | 2023.04.24 |
Coroutine 과 UniTask 비교 예제 (5) | 2023.01.21 |
[유니티 활용] ParticleSystem 으로 초간단 총알 패턴 만들기 (10) | 2023.01.18 |
댓글