📌 Unity 게임 숙련 개인과제
📌 개발 목표
필수 요구사항
메인 화면 구성
- 아이디
- 레벨
- 골드
- Status
- Inventory
Status 보기
- Status 버튼, Inventory 버튼 - 사라지기
- 우측에 캐릭터 정보 표현
- 뒤로가기 버튼을 눌러 이전 화면으로 이동
Inventory 보기
- Status 버튼, Inventory 버튼 - 사라지기
- 우측에 인벤토리 표시
- 아이템을 클릭하면 장착관리
- 장착중인 아이템은 표시
- 뒤로가기 버튼을 눌러 이전 화면으로 이동
선택 요구사항
아이템 장착 팝업 업그레이드
- 아이템을 클릭하면 해당 정보가 팝업에 나타나도록 적용
상점 기능
- 상점 버튼 추가
- 구매 완료 후 팝업
- 구매한 아이템은 인벤토리로 추가
- 상점 아이템이 넘어간다면 스크롤 되게 적용
📌 구현 기능
메인 화면
![](https://velog.velcdn.com/images/ljun970/post/b2f869bf-8c1f-46c4-a375-8ed55e44ff07/image.png)
상태창
![](https://velog.velcdn.com/images/ljun970/post/6e7372db-b059-4124-a80d-9f0abff000d5/image.png)
인벤토리 및 아이템 장착 팝업
![](https://velog.velcdn.com/images/ljun970/post/40681239-59ce-4bca-8462-6b5b5a038ef3/image.png)
아이템 장착시 표시
![](https://velog.velcdn.com/images/ljun970/post/85065175-6527-4749-8a58-ae2761633f72/image.png)
아이템 장착시 스탯 업데이트
![](https://velog.velcdn.com/images/ljun970/post/d7657451-f74d-4161-999d-852953cb2d1a/image.png)
상점
![](https://velog.velcdn.com/images/ljun970/post/f0b900a6-4cf8-4b2b-b9f9-b2d4a2e20055/image.png)
구매 완료 팝업
![](https://velog.velcdn.com/images/ljun970/post/3a02c62d-957b-4fef-afac-bd25c7c31a93/image.png)
골드 부족 팝업
![](https://velog.velcdn.com/images/ljun970/post/1f5978b2-00e9-474d-9da3-ee1b02a4a2df/image.png)
중복 아이템 장착 불가
![](https://velog.velcdn.com/images/ljun970/post/407463cc-ff7c-4b07-91b2-edc257e3bd78/image.png)
아이템 풀장착 스텟 업데이트
![](https://velog.velcdn.com/images/ljun970/post/34d3862d-944b-40c0-a34e-c0a0d04a641d/image.png)
Project Asset구성
![](https://velog.velcdn.com/images/ljun970/post/305d9fdf-95be-47b4-929e-57f824479a36/image.png)
Scriptable Object 활용
![](https://velog.velcdn.com/images/ljun970/post/80713c15-3677-4b97-a69f-d6da9f8b6501/image.png)
UI 구성
![](https://velog.velcdn.com/images/ljun970/post/0f6d00d2-35fc-4784-a10f-7452a77c2a1c/image.png)
📌 스크립트
Player
PlayerConditions.cs
[System.Serializable]
public class Condition
{
[HideInInspector]
public int currentValue;
public int startValue;
public int addValue;
public void Add(int newValue)
{
currentValue += newValue;
}
public void Subtract(int newValue)
{
currentValue -= newValue;
}
public void SaveAddValue(int newValue)
{
addValue += newValue;
}
public void SaveSubtractValue(int newValue)
{
addValue -= newValue;
}
}
[System.Serializable]
public class EquipCheck
{
public bool equipCheck;
public void EquipItem()
{
equipCheck = true;
}
public void ReleaseItem()
{
equipCheck = false;
}
}
public class PlayerConditions : MonoBehaviour
{
public Condition strikingPower;
public Condition defensivePower;
public Condition healthPoint;
public Condition gold;
public EquipCheck weapon;
public EquipCheck armor;
public EquipCheck health;
public static PlayerConditions instance;
private void Awake()
{
instance = this;
}
void Start()
{
strikingPower.currentValue = strikingPower.startValue;
defensivePower.currentValue = defensivePower.startValue;
healthPoint.currentValue = healthPoint.startValue;
gold.currentValue = gold.startValue;
weapon.equipCheck = false;
armor.equipCheck = false;
health.equipCheck = false;
}
}
Inventory.cs
public class ItemSlot
{
public ItemData item;
}
public class Inventory : MonoBehaviour
{
public ItemSlotUI[] uiSlot;
public ItemSlot[] slots;
[Header("Selected Item")]
private ItemSlot selectedItem;
private int selcetedItemIndex;
public Text selectedItemName;
public Text selectedItemDescription;
public Image selectedItemIcon;
public TextMeshProUGUI selectedItemTypeName;
public TextMeshProUGUI selectedItemTypeValue;
public Image selectedItemTypeIcon;
[Header("Item EquipCheck")]
public Text equipText;
public Button equipButton;
public Button releaseButton;
public Image reduplicationCheck;
public Image EquipScreen;
private PlayerConditions player;
public ItemData testItem;
public ItemData testItem2;
public ItemData testItem3;
public static Inventory instance;
private void Awake()
{
instance = this;
}
private void Start()
{
player = PlayerConditions.instance;
slots = new ItemSlot[uiSlot.Length];
for(int i = 0; i < slots.Length; i++)
{
slots[i] = new ItemSlot();
uiSlot[i].index = i;
uiSlot[i].Clear();
}
AddItem(testItem);
AddItem(testItem2);
AddItem(testItem3);
}
public void AddItem(ItemData item)
{
ItemSlot emptySlot = GetEmptySlot();
if(emptySlot != null)
{
emptySlot.item = item;
UpdateUI();
return;
}
}
void UpdateUI()
{
for(int i = 0; i < slots.Length; i++)
{
if (slots[i].item != null)
uiSlot[i].Set(slots[i]);
else
uiSlot[i].Clear();
}
}
public void SelectItem(int index)
{
if (slots[index].item == null)
return;
equipButton.gameObject.SetActive(false);
releaseButton.gameObject.SetActive(false);
EquipScreen.gameObject.SetActive(true);
selectedItem = slots[index];
selcetedItemIndex = index;
selectedItemName.text = selectedItem.item.itemName;
selectedItemDescription.text = selectedItem.item.description;
selectedItemIcon.sprite = selectedItem.item.icon;
selectedItemTypeName.text = string.Empty;
selectedItemTypeValue.text = string.Empty;
if (uiSlot[selcetedItemIndex].equipIcon.gameObject.activeSelf == true)
{
equipText.text = "해제 하시겠습니까?";
releaseButton.gameObject.SetActive(true);
}
else
{
equipText.text = "장착 하시겠습니까?";
equipButton.gameObject.SetActive(true);
}
selectedItemTypeIcon.color = Color.black;
for (int i = 0; i < selectedItem.item.stats.Length; i++)
{
selectedItemTypeName.text += selectedItem.item.stats[i].type.ToString();
selectedItemTypeValue.text += selectedItem.item.stats[i].value.ToString();
selectedItemTypeIcon.sprite = selectedItem.item.stats[i].icon;
}
}
public void EquipItem()
{
for (int i = 0; i < selectedItem.item.stats.Length; i++)
{
if (selectedItem.item.stats[i].type == StatsType.ATK && player.weapon.equipCheck == false)
{
player.strikingPower.SaveAddValue(selectedItem.item.stats[i].value);
player.strikingPower.Add(player.strikingPower.addValue);
player.weapon.EquipItem();
uiSlot[selcetedItemIndex].equipIcon.gameObject.SetActive(true);
}
else if (selectedItem.item.stats[i].type == StatsType.DEF && player.armor.equipCheck == false)
{
player.defensivePower.SaveAddValue(selectedItem.item.stats[i].value);
player.defensivePower.Add(player.defensivePower.addValue);
player.armor.EquipItem();
uiSlot[selcetedItemIndex].equipIcon.gameObject.SetActive(true);
}
else if (selectedItem.item.stats[i].type == StatsType.HP && player.health.equipCheck == false)
{
player.healthPoint.SaveAddValue(selectedItem.item.stats[i].value);
player.healthPoint.Add(player.healthPoint.addValue);
player.health.EquipItem();
uiSlot[selcetedItemIndex].equipIcon.gameObject.SetActive(true);
}
else
{
reduplicationCheck.gameObject.SetActive(true);
}
}
EquipScreen.gameObject.SetActive(false);
}
public void ReleaseItem()
{
for (int i = 0; i < selectedItem.item.stats.Length; i++)
{
if (selectedItem.item.stats[i].type == StatsType.ATK)
{
player.strikingPower.Subtract(player.strikingPower.addValue);
player.strikingPower.SaveSubtractValue(selectedItem.item.stats[i].value);
player.weapon.ReleaseItem();
}
else if (selectedItem.item.stats[i].type == StatsType.DEF)
{
player.defensivePower.Subtract(player.defensivePower.addValue);
player.defensivePower.SaveSubtractValue(selectedItem.item.stats[i].value);
player.armor.ReleaseItem();
}
else if (selectedItem.item.stats[i].type == StatsType.HP)
{
player.healthPoint.Subtract(player.healthPoint.addValue);
player.healthPoint.SaveSubtractValue(selectedItem.item.stats[i].value);
player.health.ReleaseItem();
}
}
uiSlot[selcetedItemIndex].equipIcon.gameObject.SetActive(false);
EquipScreen.gameObject.SetActive(false);
}
public void ClearSeletedItemSettinf()
{
selectedItem = null;
selectedItemName.text = string.Empty;
selectedItemDescription.text = string.Empty;
selectedItemIcon.sprite = null;
selectedItemTypeName.text = string.Empty;
selectedItemTypeValue.text = string.Empty;
selectedItemTypeIcon.sprite = null;
}
ItemSlot GetEmptySlot()
{
for(int i = 0; i < slots.Length; i++)
{
if (slots[i].item == null)
return slots[i];
}
return null;
}
}
Item
ItemObject.cs
public class ItemObject : MonoBehaviour
{
public ItemData Item;
}
Shop
Shop.cs
public class Shop : MonoBehaviour
{
public ItemData FireIceSword;
public ItemData BoneWeapon;
public ItemData ClamArmor;
public ItemData FourClover;
public Image buyScreen;
public Image buyFailScreen;
Inventory inventory;
PlayerConditions player;
private void Start()
{
inventory = Inventory.instance;
player = PlayerConditions.instance;
}
public void BuySwordItem()
{
GoldCheck(FireIceSword);
}
public void BuyBoneItem()
{
GoldCheck(BoneWeapon);
}
public void BuyClamItem()
{
GoldCheck(ClamArmor);
}
public void BuyCloverItem()
{
GoldCheck(FourClover);
}
private void GoldCheck(ItemData item)
{
if (player.gold.currentValue < item.value)
{
buyFailScreen.gameObject.SetActive(true);
return;
}
player.gold.currentValue -= item.value;
inventory.AddItem(item);
buyScreen.gameObject.SetActive(true);
}
}
UI
ItemSlotUI.cs
public class ItemSlotUI : MonoBehaviour
{
public Button button;
public Image icon;
public Image equipIcon;
private ItemSlot currentSlot;
public int index;
public bool equipped;
private void OnEnable()
{
equipIcon.color = Color.red;
equipIcon.enabled = equipped;
}
public void Set(ItemSlot slot)
{
currentSlot = slot;
icon.gameObject.SetActive(true);
icon.sprite = slot.item.icon;
}
public void Clear()
{
currentSlot = null;
icon.gameObject.SetActive(false);
}
public void OnItemClickButton()
{
Inventory.instance.SelectItem(index);
}
public void OnCloseEquipButton()
{
Inventory.instance.ClearSeletedItemSettinf();
Inventory.instance.EquipScreen.gameObject.SetActive(false);
}
}
UIManager.cs
public class UIManager : MonoBehaviour
{
[Header("Stats")]
public TextMeshProUGUI AttackText;
public TextMeshProUGUI DefenseText;
public TextMeshProUGUI HealthText;
public TextMeshProUGUI GoldText;
private PlayerConditions player;
private int compareGold;
private void Start()
{
player = PlayerConditions.instance;
}
private void Update()
{
if (compareGold != player.gold.currentValue)
GoldUpdate();
}
public void StatsUpdate()
{
AttackText.text = player.strikingPower.currentValue.ToString() + $" (+<color=red>{player.strikingPower.addValue.ToString()}</color>) ";
DefenseText.text = player.defensivePower.currentValue.ToString() + $" (+<color=red>{player.defensivePower.addValue.ToString()}</color>) ";
HealthText.text = player.healthPoint.currentValue.ToString() + $" (+<color=red>{player.healthPoint.addValue.ToString()}</color>) ";
}
public void GoldUpdate()
{
compareGold = player.gold.currentValue;
GoldText.text = compareGold.ToString();
}
public void OnEquipButton()
{
Inventory.instance.EquipItem();
}
public void OnReleaseButton()
{
Inventory.instance.ReleaseItem();
}
}
ScriptableObject
ItemData.cs (ScriptableObject)
public enum ItemType
{
Waepon,
Armor,
Accessories
}
public enum StatsType
{
ATK,
DEF,
HP
}
[System.Serializable]
public class ItemDataStat
{
public StatsType type;
public Sprite icon;
public int value;
}
[CreateAssetMenu(fileName = "Item", menuName = ("Creat Item"))]
public class ItemData : ScriptableObject
{
[Header("Info")]
public string itemName;
public string description;
public ItemType type;
public Sprite icon;
public int value;
[Header("ItemStats")]
public ItemDataStat[] stats;
}