public class ItemSlot
{
public ItemData item;
public int quantity;
}
public class Inventory : MonoBehaviour
{
// ์์ดํ
ํค๊ณ ๋๊ธฐ, ๋๋ ๋ฑ ๋ณ์ ์ค๋น
public ItemSlotUI[] uiSlot;
public ItemSlot[] slots;
public GameObject inventoryWindow; // ์ธ๋ฒคํ ๋ฆฌ ์ฐฝ
public Transform dropPosition; // ๋ฒ๋ฆฌ๋ ์์น
[Header("Selected Item")]
private ItemSlot selectedItem;
private int selectedItemIndex;
public TextMeshProUGUI selectedItemName; // Inventory์ TextMeshPro๋ค (์์ดํ
์ด๋ฆ, ์ค๋ช
, ์คํฏ์ด ๋ฆ, ์คํฏ ์์น)
public TextMeshProUGUI selectedItemDesciption;
public TextMeshProUGUI selectedItemStatNames;
public TextMeshProUGUI selectedItemStatValues;
public GameObject useButton; // Inventory์ Button๋ค (์ฌ์ฉ, ์ฐฉ์ฉ, ํด์ , ๋ฒ๋ฆฌ๊ธฐ)
public GameObject equipButton;
public GameObject unEquipButton;
public GameObject dropButton;
private int curEquipIndex;
private PlayerController controller;
private PlayerConditions condition;
[Header("Events")]
public UnityEvent onOpenInventory;
public UnityEvent onCloseInventory;
public static Inventory instance;
private void Awake()
{
instance = this;
controller = GetComponent<PlayerController>();
condition = GetComponent<PlayerConditions>();
}
private void Start()
{
inventoryWindow.SetActive(false); // ์ฒ์์๋ ์ธ๋ฒคํ ๋ฆฌ๋ฅผ ๊บผ์ค๋ค.
slots = new ItemSlot[uiSlot.Length];
// UI ์ฌ๋กฏ๋ค ์ด๊ธฐํ
for(int i = 0; i < slots.Length; i++)
{
slots[i] = new ItemSlot();
uiSlot[i].index = i;
uiSlot[i].Clear();
}
ClearSeletecItemWindow();
}
// ๋ฒํผ(Tap)์ ๋๋ฅด๋ฉด
public void OnInventoryButton(InputAction.CallbackContext callbackContext)
{
if(callbackContext.phase == InputActionPhase.Started)
{
Toggle(); // Toggle() : ์ผ์ ธ์์ผ๋ฉด ๊บผ์ฃผ๊ณ ๊บผ์ ธ์์ผ๋ฉด ์ผ์ค๋ค.
}
}
public void Toggle()
{
if(inventoryWindow.activeInHierarchy) // activeInHierarchy : Hierarchy ์์์ ์ผ์ ธ์๋๊ฐ?
{
inventoryWindow.SetActive(false);
onCloseInventory?.Invoke();
controller.ToggleCursor(false);
}
else
{
inventoryWindow.SetActive(true);
onOpenInventory?.Invoke();
controller.ToggleCursor(true);
}
}
public bool IsOpen()
{
return inventoryWindow.activeInHierarchy;
}
// Eํค๋ฅผ ๋๋ฌ ์์ดํ
์ ์ฃผ์ ์ ๋, ์ฒ๋ฆฌ
public void AddItem(ItemData item)
{
if(item.canStack) // .canStack : ์์ดํ
์ด ์์ผ์ ์๋ ๊ฒ์ด๋?
{
ItemSlot slotToStackTo = GetItemStack(item);
if(slotToStackTo != null)
{
slotToStackTo.quantity++; // ์ฐธ์ด๋ฉด ์คํ์ ์์๋ผ
UpdateUI();
return;
}
}
// ์์์ ์๋๊ฒ ์๋๋ฉด ๋น์นธ(Empty)์ ์ฐพ์ ๊ฐ๋ผ
ItemSlot emptySlot = GetEmptySlot();
if(emptySlot != null)
{
emptySlot.item = item;
emptySlot.quantity = 1;
UpdateUI();
return;
}
// ๊ฝ ์ฐผ๋ค๋ฉด?
ThrowItem(item); // ์์ดํ
์ ๋ค์ ๋์ง๋ค.
}
void ThrowItem(ItemData item)
{
// ๋ด ์์ ๋๋์ง์ (dropPosition)์ ์ก์๋ ๊ณณ์ ๋๋คํ ํ์ ์ ๋ฐ๊ณ ์ ๋ค์ ์ถ๋ ฅํด๋ผ (์ธ๋ฒคํ ๋ฆฌ๊ฐ ๊ฝ ์ฐผ์ ๋)
Instantiate(item.dropPrefab, dropPosition.position, Quaternion.Euler(Vector3.one * Random.value * 360f));
}
// slots์ ์๋ ๋ฐ์ดํฐ๋ก uislot์ ์ต์ ํ๋ฅผ ์์ผ์ค๋ค.
void UpdateUI()
{
for(int i = 0; i < slots.Length; i++)
{
if (slots[i].item != null)
uiSlot[i].Set(slots[i]); // slots[i]์ ์์ดํ
์ด ์๋ค๋ฉด ui์ Set
else
uiSlot[i].Clear(); // ์๋ค๋ฉด Clear
}
}
ItemSlot GetItemStack(ItemData item)
{
for(int i = 0; i < slots.Length; i++) // slots์ ๋๋ฉด์
{
// slots์ ๋งค๊ฐ๋ณ์๋ก ๋ค์ด์จ item์ด ์กด์ฌํ๊ณ ๊ทธ ๊ฐฏ์๊ฐ ๊ทธ ์์ดํ
์ ์ต๋์คํ๊ฐฏ์๋ฅผ ๋์ง ์๋ค๋ฉด
if (slots[i].item == item && slots[i].quantity < item.maxStackAmount)
return slots[i];
}
return null;
}
ItemSlot GetEmptySlot()
{
for (int i = 0; i < slots.Length; i++) // slots์ ๋๋ฉด์
{
if (slots[i].item == null) // ๋น์นธ์ ์ฐพ์๋ผ
return slots[i];
}
return null;
}
public void SelectItem(int index)
{
if (slots[index].item == null)
return; // ์์ดํ
์ด ์์ผ๋ฉด Select์ ํ ์ ์์ผ๋ return
selectedItem = slots[index];
selectedItemIndex = index;
selectedItemName.text = selectedItem.item.displayName;
selectedItemDesciption.text = selectedItem.item.description;
selectedItemStatNames.text = string.Empty;
selectedItemStatValues.text = string.Empty;
for(int i = 0; i < selectedItem.item.consumables.Length; i++)
{
selectedItemStatNames.text += selectedItem.item.consumables[i].type.ToString() + "\n";
selectedItemStatValues.text += selectedItem.item.consumables[i].value.ToString() + "\n";
}
useButton.SetActive(selectedItem.item.type == ItemType.Consumable); // ์๋ชจ ๋ฒํผ
equipButton.SetActive(selectedItem.item.type == ItemType.Equipable && !uiSlot[index].equipped); // ์ฅ์ฐฉ , && !uiSlot[index].equipped : ์ฅ์ฐฉ์ ์ํ๊ณ ์๋?
unEquipButton.SetActive(selectedItem.item.type == ItemType.Equipable && uiSlot[index].equipped); // ํด์ , ์ฅ์ฐฉ์ ํ๊ณ ์๋๊ฐ
dropButton.SetActive(true); // ๋๋ ๋ฒํผ
}
// ์ด๊ธฐํ ์์
private void ClearSeletecItemWindow()
{
selectedItem = null;
selectedItemName.text = string.Empty;
selectedItemDesciption.text = string.Empty;
selectedItemStatNames.text = string.Empty;
selectedItemStatValues.text = string.Empty;
useButton.SetActive(false);
useButton.SetActive(false);
unEquipButton.SetActive(false);
dropButton.SetActive(false);
}
// ๊ฐ๊ฐ์ ๋ฒํผ๋ค์ด ๋๋ ธ์ ๋, ์คํํ ๋ฉ์๋๋ค OnUseButton() ~ OnDropButton()
public void OnUseButton()
{
if(selectedItem.item.type == ItemType.Consumable) // ์๋ชจ์ฑ ์์ดํ
์ธ๊ฐ?
{
for(int i = 0; i < selectedItem.item.consumables.Length; i++)
{
switch(selectedItem.item.consumables[i].type)
{
case ConsumableType.Health:
condition.Heal(selectedItem.item.consumables[i].value);
break;
case ConsumableType.Hunger:
condition.Eat(selectedItem.item.consumables[i].value);
break;
}
}
}
RemoveSelectedItem(); // ์ฌ์ฉํ ์์ดํ
์ ์ญ์
}
public void OnEquipButton()
{
}
void UnEquip(int index)
{
}
public void OnUnEquipButton()
{
}
public void OnDropButton()
{
ThrowItem(selectedItem.item);
RemoveSelectedItem();
}
private void RemoveSelectedItem()
{
selectedItem.quantity--; // quantity : ๊ฐฏ์
if(selectedItem.quantity <= 0)
{
if (uiSlot[selectedItemIndex].equipped)
{
UnEquip(selectedItemIndex); // ์์ดํ
์ Removeํ๋๋ฐ ์ฅ์ฐฉ์ค์ด๋ฉด UnEquip ํด๋ผ
}
selectedItem.item = null;
ClearSeletecItemWindow();
}
UpdateUI();
}
public void RemoveItem(ItemData item)
{
}
public bool HasItems(ItemData item, int quantity)
{
return false;
}
}
public class ItemSlotUI : MonoBehaviour
{
public Button button;
public Image icon;
public TextMeshProUGUI quatityText;
private ItemSlot curSlot;
private Outline outline;
public int index;
public bool equipped;
private void Awake()
{
outline = GetComponent<Outline>();
}
private void OnEnable()
{
outline.enabled = equipped;
}
// ItemSlot์ ์ ๋ณด๋ฅผ ๋ณด๋ด์ฃผ๋ฉด ์ฌ๊ธฐ์ ์
ํ
์ ํด์ค๋ค.
public void Set(ItemSlot slot)
{
curSlot = slot;
icon.gameObject.SetActive(true);
icon.sprite = slot.item.icon;
quatityText.text = slot.quantity > 1 ? slot.quantity.ToString() : string.Empty;
if (outline != null)
{
outline.enabled = equipped;
}
}
// ์ฌ๋กฏ ์ด๊ธฐํ
public void Clear()
{
curSlot = null;
icon.gameObject.SetActive(false);
quatityText.text = string.Empty;
}
public void OnButtonClick()
{
Inventory.instance.SelectItem(index);
}
}
Player - Inventory ์ถ๊ฐ
UI Slots 14๊ฐ๋ฅผ ์ดํจํ์ฌ UI์ฐ๊ฒฐ
์นด๋ฉ๋ผ๋ฅผ ํ๋๋ง ์ฐ๋๊ฒฝ์ฐ ์ฅ์ฐฉ๋ ๋ฌด๊ธฐ๊ฐ (๋ค๋ฅธ๋ฌผ์ฒด์)๊ฐ๋ ค์ง๋ ๋ฌธ์ ๋ฐ์
๋ฌด๊ธฐ๋ง์ ์ฐ๋ ์นด๋ฉ๋ผ ์ค๋น
์๋์ ๊ฐ์ด ์ค์
๋น ์ค๋ธ์ ํธ๋ก ๋ฌด๊ธฐ ์ค๋ธ์ ํธ ์์ฑ
๋ ์ด์ด "Equip" ์ค์
๊ด๋ จ ๋ฌด๊ธฐ ๋ชจ๋ธ์ ํ์์ ์ถ๊ฐ
public class Equip : MonoBehaviour
{
public virtual void OnAttackInput()
{
}
}
public class EquipManager : MonoBehaviour
{
public Equip curEquip;
public Transform equipParent;
private PlayerController controller;
private PlayerConditions conditions;
// SingleTon
public static EquipManager instance;
private void Awake()
{
instance = this;
controller = GetComponent<PlayerController>();
conditions = GetComponent<PlayerConditions>();
}
public void OnAttackInput(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed && curEquip != null && controller.canLook)
{
curEquip.OnAttackInput();
}
}
public void EquipNew(ItemData item)
{
UnEquip();
curEquip = Instantiate(item.equipPrefab, equipParent).GetComponent<Equip>();
}
public void UnEquip()
{
if (curEquip != null) // ๋ญ๊ฐ ์ฅ์ฐฉ ํ๊ณ ์๋ค๋ฉด?
{
Destroy(curEquip.gameObject);
curEquip = null;
}
}
}
public class EquipTool : Equip
{
public float attackRate;
private bool attacking;
public float attackDistance;
[Header("Resource Gathering")]
public bool doesGatherResources;
[Header("Combat")]
public bool doseDealDamage;
public int damage;
private Animator animator;
private Camera _camera;
private void Awake()
{
_camera = Camera.main;
animator = GetComponent<Animator>();
}
public override void OnAttackInput()
{
if(!attacking)
{
attacking = true;
animator.SetTrigger("Attack");
Invoke("OnCanAttack", attackRate);
}
}
void OnCanAttack()
{
attacking = false;
}
}
Animator ์ถ๊ฐ
Animator Controller ์์ฑ ๋ฐ ์ถ๊ฐ
Attack Trigger ์์ฑ
์ ๋๋ฉ์ด์ Transition ์์ฑ
Idel โ Attack : Conditions (Attack), Has Exit Time (์ฒดํฌ ํด์ )
Attack โ Idle : Has Exit Time (์ฒดํฌ)
''' ์ถ๊ฐ
[Header("Equip")]
public GameObject equipPrefab;
๋น ์ค๋ธ์ ํธ ์์ฑ - Resource_Tree ์ด๋ฆ ๋ณ๊ฒฝ
ํธ๋ฆฌ ๋ชจ๋ธ ์ถ๊ฐ
Layer "Resource"๋ณ๊ฒฝ
public class Resource : MonoBehaviour
{
public ItemData itemToGive;
public int quantityPerHit = 1; // ์๋
public int capacity; // ์ด๋
public void Gather(Vector3 hitpoint, Vector3 hitNormal)
{
for(int i = 0; i < quantityPerHit; i++)
{
if(capacity <= 0) { break; }
capacity -= 1;
// ์ถฉ๋์ ๋ํ ๋ฐฉํฅ๋ฒกํฐ๋ฅผ ๋๊ฒจ์ค๋ค. (์ถฉ๋์ด ์ผ์ด๋ ๊ณณ์์ ๋๋ฅผ ๋ฐ๋ผ๋ณด๋ ๋ฐฉํฅ์ผ๋ก ์์ฑ์ ํ๋ค.)
Instantiate(itemToGive.dropPrefab, hitpoint + Vector3.up, Quaternion.LookRotation(hitNormal, Vector3.up));
}
if (capacity <= 0)
Destroy(gameObject);
}
}
-----------------------------------์๋ต ์๋ ๋ด์ฉ ์ถ๊ฐ
public void OnHit()
{
// ํ๋ฉด ๊ฐ์ด๋ฐ์ Ray๋ฅผ ์ด์
Ray ray = _camera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.Raycast(ray, out hit, attackDistance)) // attackDistance : ์ฌ๊ฑฐ๋ฆฌ
{
// ์ด๋ค ํ์
์ธ์ง ์ฒดํฌ
if (doesGatherResources && hit.collider.TryGetComponent(out Resource resource)) // ์์ ๋๊ตฌ ํ์
{
resource.Gather(hit.point, hit.normal); // (์์น, ๋ฐฉํฅ)
}
// ๋ง์ ๋์์ด IDamagable ๋ฅผ ์์๋ฐ์๋ค๋ฉด (๋ฐ๋ฏธ์ง๋ฅผ ์
๋ ํ์
์ด๋ผ๋๊ฒ)
if (doesDealDamage && hit.collider.TryGetComponent(out IDamagable damageable)) // ์ ํฌ์ฉ ๋๊ตฌ ํ์
{
damageable.TakePhysicalDamage(damage); // ๋ฐ๋ฏธ์ง๋ฅผ ์ค๋ค.
}
}
}
public virtual void OnAttackInput(PlayerConditions conditions)
{
}
''' ์๋ต
public float useStamina;
''' ์๋ต
- //public override void OnAttackInput()
+ public override void OnAttackInput(PlayerConditions conditions)
{
if(!attacking)
{
- //attacking = true;
- //animator.SetTrigger("Attack");
- //Invoke("OnCanAttack", attackRate);
+ if (conditions.UseStamina(useStamina))
+ {
+ attacking = true;
+ animator.SetTrigger("Attack");
+ Invoke("OnCanAttack", attackRate);
+ }
}
}
''' ์๋ต
if(context.phase == InputActionPhase.Performed && curEquip != null && controller.canLook)
{
- //curEquip.OnAttackInput();
+ curEquip.OnAttackInput(conditions);
}
}
Discover the simplicity of checking today's Bonoloto results on our website. Just enter your ticket number, and we'll promptly generate the outcome for you. Our platform provides a user-friendly interface, ensuring a seamless experience every time. Don't forget to bookmark our website for easy access to the Bonoloto results. Additionally, you https://comprobar-bonoloto.es/ can verify the Bonoloto QR on our platform by entering your ticket number, and we'll instantly display the results. Checking Bonoloto with QR code is straightforward on our website. Make sure to save it to your favorites for quick access.