📌 Unity 게임 숙련 개인과제
📌 개발 목표
필수 요구사항
메인 화면 구성
- 아이디
- 레벨
- 골드
- Status
- Inventory
Status 보기
- Status 버튼, Inventory 버튼 - 사라지기
- 우측에 캐릭터 정보 표현
- 뒤로가기 버튼을 눌러 이전 화면으로 이동
Inventory 보기
- Status 버튼, Inventory 버튼 - 사라지기
- 우측에 인벤토리 표시
- 아이템을 클릭하면 장착관리
- 장착중인 아이템은 표시
- 뒤로가기 버튼을 눌러 이전 화면으로 이동
선택 요구사항
아이템 장착 팝업 업그레이드
- 아이템을 클릭하면 해당 정보가 팝업에 나타나도록 적용
상점 기능
- 상점 버튼 추가
- 구매 완료 후 팝업
- 구매한 아이템은 인벤토리로 추가
- 상점 아이템이 넘어간다면 스크롤 되게 적용
📌 구현 기능
메인 화면
상태창
인벤토리 및 아이템 장착 팝업
아이템 장착시 표시
아이템 장착시 스탯 업데이트
상점
구매 완료 팝업
골드 부족 팝업
중복 아이템 장착 불가
아이템 풀장착 스텟 업데이트
Project Asset구성
Scriptable Object 활용
UI 구성
📌 스크립트
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;
}