种田RPG游戏(五)

一、重新设置物品栏

1、打开Scripts-Inventory文件新建 ItemSlotData.cs

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

[System.Serializable]
//单独的类
public class ItemSlotData
{
    public ItemData itemData;//ItemData对象(收获的物品)
    public int quantity;//数量
    //构造函数:用于创建 ItemSlotData 实例
    public ItemSlotData(ItemData itemData, int quantity)
    {
        this.itemData = itemData;
        this.quantity = quantity;
        ValidateQuantity();
    }
    // 重载的构造函数:用于创建 ItemSlotData 实例,数量默认为1
    public ItemSlotData(ItemData itemData)
    {
        this.itemData = itemData;
        quantity = 1;
        ValidateQuantity();
    }
    // 增加数量,默认增加1
    public void AddQuantity()
    {
        AddQuantity(1);
    }
    //堆叠物品(根据传入的参数增加数量)
    public void AddQuantity(int amountToAdd)
    {
        quantity += amountToAdd;
    }
    //消耗物品:移除一个物品,将物品槽中的物品数-1
    public void Remove()
    {
        quantity--;
        ValidateQuantity();
    }
    // 检查数量是否小于等于0或物品数据是否为空,如果是则清空物品槽
    private void ValidateQuantity()
    {
        if (quantity <= 0 || itemData == null)
        {
            Empty();
        }
    }
    //直接清空物品槽,将物品数据和数量重置为默认值
    public void Empty()
    {
        itemData = null;
        quantity = 0;
    }
}

2、编辑InventoryManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static InventorySlot;

public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(this);
        }
        else
        {
            Instance = this;
        }
    }

    [Header("Tools")]
    //将ItemData类型更改为ItemSlots
    //重命名tools为toolSlots,重命名equippedTool为equippedToolSlot
    //将public更改为 private

    private ItemSlotData[] toolSlots = new ItemSlotData[8];
    private ItemSlotData equippedToolSlot = null;

    [Header("Items")]
    //将ItemData类型更改为ItemSlots
    //重命名items为itemSlots,equippedItem为equippedItemSlot
    private ItemSlotData[] itemSlots = new ItemSlotData[8];
    private ItemSlotData equippedItemSlot = null;

    public Transform handPoint;

    public void InventoryToHand(int slotIndex, InventorySlot.InventoryType inventoryType)
    {
        /*注释这个方法
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            ItemData itemToEquip = itemSlots[slotIndex];
            itemSlots[slotIndex] = equippedItemSlots;
            equippedItemSlots = itemToEquip;

            //调用收割作物的方法
            RenderHand();
        }
        else
        {
            ItemData toolToEquip = toolSlots[slotIndex];
            toolSlots[slotIndex] = equippedToolSlot;
            equippedToolSlot = toolToEquip;
        }
        UIManager.Instance.RenderInventory();
        */
    }
    public void HandToInventory(InventorySlot.InventoryType inventoryType)
    {
        /*注释这个方法
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            for (int i = 0; i < itemSlots.Length; i++)
            {
                if (itemSlots[i] == null)
                {
                    itemSlots[i] = equippedItemSlot;
                    equippedItemSlot = null; 
                    break;
                }
            }
            RenderHand();
        }
        else
        {
            for(int i = 0;i < toolSlots.Length; i++)
            {
                if(toolSlots[i] == null)
                {
                    toolSlots[i] = equippedToolSlot;
                    equippedToolSlot = null;
                    break;
                }
            }
        }
        UIManager.Instance.RenderInventory();*/
    }
    public void RenderHand()
    {
        if(handPoint.childCount>0)
        {
            Destroy(handPoint.GetChild(0).gameObject);
        }
        if(equippedItemSlot != null)
        {
            //更改调用的方法
            Instantiate(GetEquippedSlotItem(InventorySlot.InventoryType.Item).gameModel, handPoint);
        }
    }
    //
    public ItemData GetEquippedSlotItem(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot.itemData;
        }
        return equippedToolSlot.itemData;
    }
    //
    public ItemSlotData GetEquippedSlot(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot;
        }
        return equippedToolSlot;
    }
    //
    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }
}

3、编辑InventorySlot.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class InventorySlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,IPointerClickHandler
{
    ItemData itemToDisplay;
    //显示数量
    int quantity;

    public Image itemDisplayImage;

    public enum InventoryType
    {
        Item, Tool
    }
    public InventoryType inventoryType;

    int slotIndex;
    //更改参数类型
    public void Display(ItemSlotData itemSlot)
    {
        //增加变量和数量
        itemToDisplay = itemSlot.itemData;
        quantity = itemSlot.quantity;

        if (itemToDisplay != null && itemToDisplay.thumbnail != null)
        {
            itemDisplayImage.sprite = itemToDisplay.thumbnail;
            //删除this.itemToDisplay = itemToDisplay;
            itemDisplayImage.gameObject.SetActive(true);
            return;
        }
        itemDisplayImage.gameObject.SetActive(false);
        this.itemToDisplay = null;
    }

    public void AssignIndex(int slotIndex)
    {
        this.slotIndex = slotIndex;
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        UIManager.Instance.DisplayItemInfo(itemToDisplay);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        UIManager.Instance.DisplayItemInfo(null);
    }

    public virtual void OnPointerClick(PointerEventData eventData)
    {
        InventoryManager.Instance.InventoryToHand(slotIndex,inventoryType);
    }
}

4、编辑UIManager.cs,

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

public class UIManager : MonoBehaviour, ITimeTracker
{
    public static UIManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [Header("Startas Bar")]
    public Image toolEquipSlotImage;
    public Text timeText;
    public Text dateText;

    [Header("Inventory System")]

    public GameObject inventoryPanel;
    public HandInventorySlot toolHandSlot;
    public InventorySlot[] toolSlots;
    public HandInventorySlot itemHandSlot;
    public InventorySlot[] itemSlots;

    public Text itemNameText;
    public Text itemDescriptionText;

    private void Start()
    {
        RenderInventory();
        AssignSlotIndex();
        TimeManager.Instance.RegisterTracker(this);
    }
    public void AssignSlotIndex()
    {
        for (int i = 0; i < toolSlots.Length; i++)
        {
            toolSlots[i].AssignIndex(i);
            itemSlots[i].AssignIndex(i);
        }
    }

    //更改参数
    public void RenderInventory(ItemSlotData[] inventoryToolSlot,ItemSlotData[] inventoryItemSlots)
    {
        
        //ItemSlotData[] inventoryToolSlots = InventoryManager.Instance.GetInventorySlots(InventorySlot.InventoryType.Tool);

        RenderInventoryPanel(inventoryToolSlot, toolSlots);

        RenderInventoryPanel(inventoryItemSlots, itemSlots);
        //
        toolHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Tool));
        itemHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Item));
        ItemData equippedTool = InventoryManager.Instance.GetEquippedSlotItem(InventorySlot.InventoryType.Tool);
        if (equippedTool != null)
        {
            toolEquipSlotImage.sprite = equippedTool.thumbnail;
            toolEquipSlotImage.gameObject.SetActive(true);
            return;
        }
        toolEquipSlotImage.gameObject.SetActive(false);
    }
    //更改参数类型
    void RenderInventoryPanel(ItemSlotData[] slots, InventorySlot[] uiSlots)
    {
        for (int i = 0; i < uiSlots.Length; i++)
        {
            uiSlots[i].Display(slots[i]);
        }
    }
    public void ToggleInventoryPanel()
    {
        inventoryPanel.SetActive(!inventoryPanel.activeSelf);
        RenderInventory();
    }

    public void DisplayItemInfo(ItemData data)
    {
        if (data == null)
        {
            itemNameText.text = "";
            itemDescriptionText.text = "";
            return;
        }
        itemNameText.text = data.name;
        itemDescriptionText.text = data.description;
    }
    public void ClockUpdate(GameTimestamp timestamp)
    {
        int hours = timestamp.hour;
        int minutes = timestamp.minute;

        string prefix = "AM ";
        if (hours > 12)
        {
            prefix = "PM ";
            hours -= 12;
        }
        timeText.text = prefix + hours + ":" + minutes.ToString("00");
        int day = timestamp.day;
        string season = timestamp.season.ToString();
        string dayOfTheWeek = timestamp.GetDayOfTheWeek().ToString();

        dateText.text = season + " " + day + " (" + dayOfTheWeek +")";
    }
}

5、编辑InventoryManager.cs,增加一个新的ItemSlotData对象组

    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }

6、编辑UIManager.cs,

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

public class UIManager : MonoBehaviour, ITimeTracker
{
    public static UIManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [Header("Startas Bar")]
    public Image toolEquipSlotImage;
    public Text timeText;
    public Text dateText;

    [Header("Inventory System")]

    public GameObject inventoryPanel;
    public HandInventorySlot toolHandSlot;
    public InventorySlot[] toolSlots;
    public HandInventorySlot itemHandSlot;
    public InventorySlot[] itemSlots;

    public Text itemNameText;
    public Text itemDescriptionText;

    private void Start()
    {
        RenderInventory();
        AssignSlotIndex();
        TimeManager.Instance.RegisterTracker(this);
    }
    public void AssignSlotIndex()
    {
        for (int i = 0; i < toolSlots.Length; i++)
        {
            toolSlots[i].AssignIndex(i);
            itemSlots[i].AssignIndex(i);
        }
    }
    //删除参数
    public void RenderInventory()
    {
        //新增
        ItemSlotData[] inventoryToolSlots = InventoryManager.Instance.GetInventorySlots(InventorySlot.InventoryType.Tool);
        ItemSlotData[] inventoryItemSlots = InventoryManager.Instance.GetInventorySlots(InventorySlot.InventoryType.Item);

        RenderInventoryPanel(inventoryToolSlots, toolSlots);
        RenderInventoryPanel(inventoryItemSlots, itemSlots);
        toolHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Tool));
        itemHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Item));
        ItemData equippedTool = InventoryManager.Instance.GetEquippedSlotItem(InventorySlot.InventoryType.Tool);
        if (equippedTool != null)
        {
            toolEquipSlotImage.sprite = equippedTool.thumbnail;
            toolEquipSlotImage.gameObject.SetActive(true);
            return;
        }
        toolEquipSlotImage.gameObject.SetActive(false);
    }
    //更改参数类型
    void RenderInventoryPanel(ItemSlotData[] slots, InventorySlot[] uiSlots)
    {
        for (int i = 0; i < uiSlots.Length; i++)
        {
            uiSlots[i].Display(slots[i]);
        }
    }
    public void ToggleInventoryPanel()
    {
        inventoryPanel.SetActive(!inventoryPanel.activeSelf);
        RenderInventory();
    }

    public void DisplayItemInfo(ItemData data)
    {
        if (data == null)
        {
            itemNameText.text = "";
            itemDescriptionText.text = "";
            return;
        }
        itemNameText.text = data.name;
        itemDescriptionText.text = data.description;
    }
    public void ClockUpdate(GameTimestamp timestamp)
    {
        int hours = timestamp.hour;
        int minutes = timestamp.minute;

        string prefix = "AM ";
        if (hours > 12)
        {
            prefix = "PM ";
            hours -= 12;
        }
        timeText.text = prefix + hours + ":" + minutes.ToString("00");
        int day = timestamp.day;
        string season = timestamp.season.ToString();
        string dayOfTheWeek = timestamp.GetDayOfTheWeek().ToString();

        dateText.text = season + " " + day + " (" + dayOfTheWeek +")";
    }
}

7、编辑InventoryManager.cs

    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }
    //新增方法
    public bool SlotEquipped(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot != null;
        }
        return equippedToolSlot != null;
    }

8、编辑PlayerInteractor.cs

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

public class PlayerInteractor : MonoBehaviour
{
    PlayerController playerController;
    Land selectLand = null;
    InteractableObject selectedInteractable = null;
    void Start()
    {
        playerController = transform.parent.GetComponent<PlayerController>();
    }

    void Update()
    {
        RaycastHit hit;
        if (Physics.Raycast(transform.position, Vector3.down, out hit, 1))
        {
            OnInteractableHit(hit);
        }
    }
    void OnInteractableHit(RaycastHit hit)
    {
        Collider other = hit.collider;
        if (other != null && other.CompareTag("Land"))
        {
            Land land = other.GetComponent<Land>();
            if (land != null)
            {
                SelectLand(land);
                return;
            }
        }
        //
        if (other.CompareTag("Item"))
        {
            selectedInteractable = other.GetComponent<InteractableObject>();
            return;
        }

        if(selectedInteractable != null)
        {
            selectedInteractable = null;
        }

        if (selectLand != null)
        {
            selectLand.Select(false);
            selectLand = null;
        }
    }

    void SelectLand(Land land)
    {
        if (land == null)
        {
            Debug.Log("你没有选择田地!");
            return;
        }
        if (selectLand != null)
        {
            selectLand.Select(false);
        }
        selectLand = land;
        land.Select(true);
    }

    public void Interact()
    {
        //更改条件
        if(InventoryManager.Instance.SlotEquipped(InventorySlot.InventoryType.Item))
        {
            return;
        }

        if(selectLand != null)
        {
            selectLand.Interact();
            return;
        }
        Debug.Log("没站在田地里");
    }
    public void ItemInteract()
    {
        //更改条件
        if (InventoryManager.Instance.SlotEquipped(InventorySlot.InventoryType.Item))
        {
            InventoryManager.Instance.HandToInventory(InventorySlot.InventoryType.Item);
            return;
        }
        if(selectedInteractable != null)
        {
            selectedInteractable.Pickup();
        }
    }
}

9、编辑Land.cs

    public void Interact()
    {
        //更改
        ItemData toolSlot = InventoryManager.Instance.GetEquippedSlotItem(InventorySlot.InventoryType.Tool);

        if(toolSlot == null)
        {
            return;
        }
        EquipmentData equipmentTool = toolSlot as EquipmentData;
        if (equipmentTool != null)
        {
            EquipmentData.ToolType toolType = equipmentTool.toolType;

            switch (toolType)
            {
                case EquipmentData.ToolType.Hoe:
                    SwitchLandStatus(LandStatus.Farmland); break;
                case EquipmentData.ToolType.WateringCan:
                    SwitchLandStatus(LandStatus.Watered); break;
                //铲除作物
                case EquipmentData.ToolType.Shovel:
                    if(cropPlanted != null)
                    {
                        Destroy(cropPlanted.gameObject);
                    }
                    break;
            }
            return;
        }
        SeedData seedTool = toolSlot as SeedData;
        if (seedTool != null && landStatus !=LandStatus.Soil && cropPlanted==null)
        {
            GameObject cropObject =Instantiate(cropPrefab ,transform);
            cropObject.transform.position = new Vector3(transform.position.x,0f,transform.position.z);
            cropPlanted = cropObject.GetComponent<CropBehaviour>();
            cropPlanted.Plant(seedTool);
        }
    }

10、编辑InventoryManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static InventorySlot;

public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(this);
        }
        else
        {
            Instance = this;
        }
    }

    [Header("Tools")]
    //将ItemData类型更改为ItemSlots
    //重命名tools为toolSlots,重命名equippedTool为equippedToolSlot
    //将public更改为 private

    private ItemSlotData[] toolSlots = new ItemSlotData[8];
    private ItemSlotData equippedToolSlot = null;

    [Header("Items")]
    //将ItemData类型更改为ItemSlots
    //重命名items为itemSlots,equippedItem为equippedItemSlot
    private ItemSlotData[] itemSlots = new ItemSlotData[8];
    private ItemSlotData equippedItemSlot = null;

    public Transform handPoint;

    public void InventoryToHand(int slotIndex, InventorySlot.InventoryType inventoryType)
    {
        /*注释这个方法
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            ItemData itemToEquip = itemSlots[slotIndex];
            itemSlots[slotIndex] = equippedItemSlots;
            equippedItemSlots = itemToEquip;

            //调用收割作物的方法
            RenderHand();
        }
        else
        {
            ItemData toolToEquip = toolSlots[slotIndex];
            toolSlots[slotIndex] = equippedToolSlot;
            equippedToolSlot = toolToEquip;
        }
        UIManager.Instance.RenderInventory();
        */
    }
    public void HandToInventory(InventorySlot.InventoryType inventoryType)
    {
        /*注释这个方法
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            for (int i = 0; i < itemSlots.Length; i++)
            {
                if (itemSlots[i] == null)
                {
                    itemSlots[i] = equippedItemSlot;
                    equippedItemSlot = null; 
                    break;
                }
            }
            RenderHand();
        }
        else
        {
            for(int i = 0;i < toolSlots.Length; i++)
            {
                if(toolSlots[i] == null)
                {
                    toolSlots[i] = equippedToolSlot;
                    equippedToolSlot = null;
                    break;
                }
            }
        }
        UIManager.Instance.RenderInventory();*/
    }
    public void RenderHand()
    {
        if(handPoint.childCount>0)
        {
            Destroy(handPoint.GetChild(0).gameObject);
        }
        if(equippedItemSlot != null)
        {
            Instantiate(GetEquippedSlotItem(InventorySlot.InventoryType.Item).gameModel, handPoint);
        }
    }

    //新增判断
    public bool IsTool(ItemData item)
    {
        EquipmentData equipment = item as EquipmentData;
        if(equipment != null)
        {
            return true;
        }
        SeedData seed = item as SeedData;
        return seed != null;
    }

    //组织代码
    #region Gets and Checks

    //
    public ItemData GetEquippedSlotItem(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot.itemData;
        }
        return equippedToolSlot.itemData;
    }
    //
    public ItemSlotData GetEquippedSlot(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot;
        }
        return equippedToolSlot;
    }
    //新增
    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }
    //新增方法
    public bool SlotEquipped(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot != null;
        }
        return equippedToolSlot != null;
    }
    #endregion
    //新增方法
    public void EquipEmptySlot(ItemData item)
    {
        if(IsTool(item))
        {
            equippedToolSlot = new ItemSlotData(item);
        }
        else
        {
            equippedItemSlot = new ItemSlotData(item);
        }
    }
}

11、编辑InteractableObject.cs

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

public class InteractableObject : MonoBehaviour
{
    public ItemData item;

    //增加virtual以便重写
    public virtual void Pickup()
    {
        InventoryManager.Instance.EquipEmptySlot(item);
        InventoryManager.Instance.RenderHand();
        Destroy(gameObject);
    }
}

12、编辑RegrowableHarvestBehaviour.cs

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

public class RegrowableHarvestBehaviour : InteractableObject
{
    CropBehaviour parentCrop;
    public void SetParent(CropBehaviour parentCrop)
    {
        this.parentCrop = parentCrop;
    }
    public override void Pickup()
    {
        //更改
        InventoryManager.Instance.EquipEmptySlot(item);
        InventoryManager.Instance.RenderHand();

        parentCrop.Regrow();
    }
}
二、设置物品数量

1、编辑InventoryManager.cs,序列化

[Header("Tools")]
//每一行增加[SerializeField]

[SerializeField] private ItemSlotData[] toolSlots = new ItemSlotData[8];
[SerializeField] private ItemSlotData equippedToolSlot = null;

[Header("Items")]
[SerializeField] private ItemSlotData[] itemSlots = new ItemSlotData[8];
[SerializeField] private ItemSlotData equippedItemSlot = null;

2、编辑InventoryManager.cs

    //新增方法
    public void OnValidate()
    {
        ValidateInventorySlots(equippedToolSlot);
        ValidateInventorySlots(equippedItemSlot);

        ValidateInventorySlots(itemSlots);
        ValidateInventorySlots(toolSlots);
    }
    //新增方法
    void ValidateInventorySlots(ItemSlotData slot)
    {
        if(slot.itemData != null &&slot.quantity == 0)
        {
            slot.quantity = 1;
        }
    }
    //新增方法
    void ValidateInventorySlots(ItemSlotData[] array)
    {
        foreach(ItemSlotData slot in array)
        {
            ValidateInventorySlots(slot);
        }
    }

3、赋值

选中Manager,找到Inspector上的InventoryManager.cs组件,赋值

4、添加物品数量文本

(1) 以HandSlot为父物体,UI-Text,重命名为QuantityText。

(2) 设置它的Rect Transform和Text

(3) 复制QuantityText,设置它的Rect Transform和Text

(4) 同样的方法,添加InventorySlot的子物体(文本)

(5) Apply预制体InventorySlot的更改

(6) 同样的方法,添加HandSlot的子物体(文本)

(7) 编辑InventorySlot.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class InventorySlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,IPointerClickHandler
{
    ItemData itemToDisplay;
    int quantity;
    //数量文本
    public Image itemDisplayImage;
    public Text quantityText;

    public enum InventoryType
    {
        Item, Tool
    }
    public InventoryType inventoryType;

    int slotIndex;
    public void Display(ItemSlotData itemSlot)
    {
        itemToDisplay = itemSlot.itemData;
        quantity = itemSlot.quantity;

        //显示数量文本
        quantityText.text = "";

        if (itemToDisplay != null && itemToDisplay.thumbnail != null)
        {
            itemDisplayImage.sprite = itemToDisplay.thumbnail;
            //显示数量文本
            if (quantity > 1)
            {
                quantityText.text = quantity.ToString();
            }
            itemDisplayImage.gameObject.SetActive(true);
            return;
        }
        itemDisplayImage.gameObject.SetActive(false);
        this.itemToDisplay = null;
    }

    public void AssignIndex(int slotIndex)
    {
        this.slotIndex = slotIndex;
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        UIManager.Instance.DisplayItemInfo(itemToDisplay);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        UIManager.Instance.DisplayItemInfo(null);
    }

    public virtual void OnPointerClick(PointerEventData eventData)
    {
        InventoryManager.Instance.InventoryToHand(slotIndex,inventoryType);
    }
}

(8) 赋值(预制体InventorySlot中)

(9) 赋值

三、

1、编辑ItemSlotData.cs

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

[System.Serializable]
public class ItemSlotData
{
    public ItemData itemData;
    public int quantity;
    public ItemSlotData(ItemData itemData, int quantity)
    {
        this.itemData = itemData;
        this.quantity = quantity;
        ValidateQuantity();
    }
    public ItemSlotData(ItemData itemData)
    {
        this.itemData = itemData;
        quantity = 1;
        ValidateQuantity();
    }
    //复制ItemSlotData对象
    public ItemSlotData(ItemSlotData slotToClone)
    {
        itemData = slotToClone.itemData;
        quantity = slotToClone.quantity;
    }

    public void AddQuantity()
    {
        AddQuantity(1);
    }
    public void AddQuantity(int amountToAdd)
    {
        quantity += amountToAdd;
    }
    public void Remove()
    {
        quantity--;
        ValidateQuantity();
    }
    //新增方法
    public bool Stackable(ItemSlotData slotToCompare)
    {
        return slotToCompare.itemData == itemData;
    }
    private void ValidateQuantity()
    {
        if (quantity <= 0 || itemData == null)
        {
            Empty();
        }
    }
    public void Empty()
    {
        itemData = null;
        quantity = 0;
    }
    //新增方法
    public bool IsEmpty()
    {
        return itemData == null;
    }
}

2、编辑InventoryManager.cs(这里有一个报错)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static InventorySlot;

public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(this);
        }
        else
        {
            Instance = this;
        }
    }

    [Header("Tools")]

    [SerializeField] private ItemSlotData[] toolSlots = new ItemSlotData[8];
    [SerializeField] private ItemSlotData equippedToolSlot = null;

    [Header("Items")]
    [SerializeField] private ItemSlotData[] itemSlots = new ItemSlotData[8];
    [SerializeField] private ItemSlotData equippedItemSlot = null;

    public Transform handPoint;

    public void InventoryToHand(int slotIndex, InventorySlot.InventoryType inventoryType)
    {
        //临时变量
        ItemSlotData handToEquip = equippedToolSlot;
        ItemSlotData[] inventoryToAlter = toolSlots;
        //装备物品槽
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            handToEquip = equippedItemSlot;
            inventoryToAlter = itemSlots;
        }
        //检查是否可以堆叠
        if (handToEquip.Stackable(inventoryToAlter[slotIndex]))
        {
            ItemSlotData slotToAlter = inventoryToAlter[slotIndex];
            handToEquip.AddQuantity(slotToAlter.quantity);
            slotToAlter.Empty();
        }
        else
        {
            ItemSlotData slotToEquip = new ItemSlotData(inventoryToAlter[slotIndex]);
            inventoryToAlter[slotIndex] = new ItemSlotData(handToEquip);
            EquipEmptySlot(slotToEquip);
        }
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            RenderHand();
        }
        //渲染
        UIManager.Instance.RenderInventory();
    }
    public void HandToInventory(InventorySlot.InventoryType inventoryType)
    {
        //临时变量
        ItemSlotData handSlot = equippedToolSlot;
        ItemSlotData[] inventoryToAlter = toolSlots;
        //装备
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            handSlot = equippedItemSlot;
            inventoryToAlter = itemSlots;
        }
        if(!StackItemToInventory(handSlot, inventoryToAlter))
        {
            for(int i =  0; i < inventoryToAlter.Length; i++)
            {
                if(inventoryToAlter[i] == null)
                {
                    inventoryToAlter[i] = new ItemSlotData(handSlot);
                    handSlot.Empty();
                    break;
                }
            }
        }
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            RenderHand();
        }
        UIManager.Instance.RenderInventory();
    }
    //新建方法
    public bool StackItemToInventory(ItemSlotData itemSlot, ItemSlotData[] inventoryArray)
    {
        for(int i = 0; i < inventoryArray.Length; i++)
        {
            if (inventoryArray[i].Stackable(itemSlot))
            {
                inventoryArray[i].AddQuantity(itemSlot.quantity);
                itemSlot.Empty();
                return true;
            }
        }
        return false;
    }
    public void RenderHand()
    {
        if(handPoint.childCount>0)
        {
            Destroy(handPoint.GetChild(0).gameObject);
        }
        //更改条件
        if(SlotEquipped(InventorySlot.InventoryType.Item))
        {
            Instantiate(GetEquippedSlotItem(InventorySlot.InventoryType.Item).gameModel, handPoint);
        }
    }


    #region Gets and Checks

    public ItemData GetEquippedSlotItem(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot.itemData;
        }
        return equippedToolSlot.itemData;
    }
    //
    public ItemSlotData GetEquippedSlot(InventorySlot.InventoryType inventoryType)
    {
        if(inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot;
        }
        return equippedToolSlot;
    }
    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }
    public bool SlotEquipped(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            //更改
            return !equippedItemSlot.IsEmpty();
        }
        //更改
        return !equippedToolSlot.IsEmpty();
    }
    public bool IsTool(ItemData item)
    {
        EquipmentData equipment = item as EquipmentData;
        if (equipment != null)
        {
            return true;
        }
        SeedData seed = item as SeedData;
        return seed != null;
    }

    #endregion
    public void EquipEmptySlot(ItemData item)
    {
        if(IsTool(item))
        {
            equippedToolSlot = new ItemSlotData(item);
        }
        else
        {
            equippedItemSlot = new ItemSlotData(item);
        }
    }
    //组织
    #region Inventory Slot validation
    public void OnValidate()
    {
        ValidateInventorySlots(equippedToolSlot);
        ValidateInventorySlots(equippedItemSlot);

        ValidateInventorySlots(itemSlots);
        ValidateInventorySlots(toolSlots);
    }
    void ValidateInventorySlots(ItemSlotData slot)
    {
        if(slot.itemData != null &&slot.quantity == 0)
        {
            slot.quantity = 1;
        }
    }
    void ValidateInventorySlots(ItemSlotData[] array)
    {
        foreach(ItemSlotData slot in array)
        {
            ValidateInventorySlots(slot);
        }
    }
    #endregion 
}

 3、编辑InventoryManager.cs,处理报错

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static InventorySlot;

public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(this);
        }
        else
        {
            Instance = this;
        }
    }

    [Header("Tools")]

    [SerializeField] private ItemSlotData[] toolSlots = new ItemSlotData[8];
    [SerializeField] private ItemSlotData equippedToolSlot = null;

    [Header("Items")]
    [SerializeField] private ItemSlotData[] itemSlots = new ItemSlotData[8];
    [SerializeField] private ItemSlotData equippedItemSlot = null;

    public Transform handPoint;

    public void InventoryToHand(int slotIndex, InventorySlot.InventoryType inventoryType)
    {
        ItemSlotData handToEquip = equippedToolSlot;
        ItemSlotData[] inventoryToAlter = toolSlots;
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            handToEquip = equippedItemSlot;
            inventoryToAlter = itemSlots;
        }
        if (handToEquip.Stackable(inventoryToAlter[slotIndex]))
        {
            ItemSlotData slotToAlter = inventoryToAlter[slotIndex];
            handToEquip.AddQuantity(slotToAlter.quantity);
            slotToAlter.Empty();
        }
        else
        {
            ItemSlotData slotToEquip = new ItemSlotData(inventoryToAlter[slotIndex]);
            inventoryToAlter[slotIndex] = new ItemSlotData(handToEquip);
            EquipHandSlot(slotToEquip);
        }
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            RenderHand();
        }
        UIManager.Instance.RenderInventory();
    }
    public void HandToInventory(InventorySlot.InventoryType inventoryType)
    {
        ItemSlotData handSlot = equippedToolSlot;
        ItemSlotData[] inventoryToAlter = toolSlots;
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            handSlot = equippedItemSlot;
            inventoryToAlter = itemSlots;
        }
        if (!StackItemToInventory(handSlot, inventoryToAlter))
        {
            for (int i = 0; i < inventoryToAlter.Length; i++)
            {
                if (inventoryToAlter[i].IsEmpty())
                {
                    inventoryToAlter[i] = new ItemSlotData(handSlot);
                    handSlot.Empty();
                    break;
                }
            }
        }
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            RenderHand();
        }
        UIManager.Instance.RenderInventory();
    }
    public bool StackItemToInventory(ItemSlotData itemSlot, ItemSlotData[] inventoryArray)
    {
        for (int i = 0; i < inventoryArray.Length; i++)
        {
            if (inventoryArray[i].Stackable(itemSlot))
            {
                inventoryArray[i].AddQuantity(itemSlot.quantity);
                itemSlot.Empty();
                return true;
            }
        }
        return false;
    }
    public void RenderHand()
    {
        if (handPoint.childCount > 0)
        {
            Destroy(handPoint.GetChild(0).gameObject);
        }
        if (SlotEquipped(InventorySlot.InventoryType.Item))
        {
            Instantiate(GetEquippedSlotItem(InventorySlot.InventoryType.Item).gameModel, handPoint);
        }
    }


    #region Gets and Checks

    public ItemData GetEquippedSlotItem(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot.itemData;
        }
        return equippedToolSlot.itemData;
    }
    public ItemSlotData GetEquippedSlot(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return equippedItemSlot;
        }
        return equippedToolSlot;
    }
    public ItemSlotData[] GetInventorySlots(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return itemSlots;
        }
        return toolSlots;
    }
    public bool SlotEquipped(InventorySlot.InventoryType inventoryType)
    {
        if (inventoryType == InventorySlot.InventoryType.Item)
        {
            return !equippedItemSlot.IsEmpty();
        }
        return !equippedToolSlot.IsEmpty();
    }
    public bool IsTool(ItemData item)
    {
        EquipmentData equipment = item as EquipmentData;
        if (equipment != null)
        {
            return true;
        }
        SeedData seed = item as SeedData;
        return seed != null;
    }

    #endregion
    public void EquipHandSlot(ItemData item)
    {
        if (IsTool(item))
        {
            equippedToolSlot = new ItemSlotData(item);
        }
        else
        {
            equippedItemSlot = new ItemSlotData(item);
        }
    }
    //新建方法,重载
    public void EquipHandSlot(ItemSlotData itemSlot)
    {
        ItemData item = itemSlot.itemData;
        if (IsTool(item))
        {
            equippedToolSlot = new ItemSlotData(itemSlot);
        }
        else
        {
            equippedItemSlot = new ItemSlotData(itemSlot);
        }
    }
    #region Inventory Slot validation
    public void OnValidate()
    {
        ValidateInventorySlots(equippedToolSlot);
        ValidateInventorySlots(equippedItemSlot);

        ValidateInventorySlots(itemSlots);
        ValidateInventorySlots(toolSlots);
    }
    void ValidateInventorySlots(ItemSlotData slot)
    {
        if (slot.itemData != null && slot.quantity == 0)
        {
            slot.quantity = 1;
        }
    }
    void ValidateInventorySlots(ItemSlotData[] array)
    {
        foreach (ItemSlotData slot in array)
        {
            ValidateInventorySlots(slot);
        }
    }
    #endregion 
}

4、编辑InventoryManager.cs,

    //新建方法
    public void ConsumeItem(ItemSlotData itemSlot)
    {
        if (itemSlot.IsEmpty())
        {
            Debug.LogError("没有种子了");
            return;
        }
        itemSlot.Remove();
        RenderHand();
        UIManager.Instance.RenderInventory();
    }

5、编辑Land.cs

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

public class Land : MonoBehaviour, ITimeTracker
{
    public enum LandStatus { Soil, Farmland, Watered }
    public LandStatus landStatus;
    public Material soilMat, farmlandMat, wateredMat;
    new Renderer renderer;

    public GameObject select;
    GameTimestamp timeWatered;

    [Header("Crops")]
    public GameObject cropPrefab;
    CropBehaviour cropPlanted = null;
    void Start()
    {
        renderer = GetComponent<Renderer>();
        SwitchLandStatus(LandStatus.Soil);
        //select.SetActive(false);
        Select(false);
        TimeManager.Instance.RegisterTracker(this);
    }

    public void SwitchLandStatus(LandStatus statusToSwitch)
    {
        landStatus = statusToSwitch;
        Material materialToSwitch = soilMat;
        switch (statusToSwitch)
        {
            case LandStatus.Soil: materialToSwitch = soilMat; break;
            case LandStatus.Farmland: materialToSwitch = farmlandMat; break;
            case LandStatus.Watered:
                materialToSwitch = wateredMat;
                timeWatered = TimeManager.Instance.GetGameTimestamp();
                break;
        }
        renderer.material = materialToSwitch;
    }
    public void Select(bool toggle)
    {
        select.SetActive(toggle);
    }

    public void Interact()
    {
        ItemData toolSlot = InventoryManager.Instance.GetEquippedSlotItem(InventorySlot.InventoryType.Tool);

        //更改条件
        if(!InventoryManager.Instance.SlotEquipped(InventorySlot.InventoryType.Tool))
        {
            return;
        }
        EquipmentData equipmentTool = toolSlot as EquipmentData;
        if (equipmentTool != null)
        {
            EquipmentData.ToolType toolType = equipmentTool.toolType;

            switch (toolType)
            {
                case EquipmentData.ToolType.Hoe:
                    SwitchLandStatus(LandStatus.Farmland); break;
                case EquipmentData.ToolType.WateringCan:
                    SwitchLandStatus(LandStatus.Watered); break;
                case EquipmentData.ToolType.Shovel:
                    if(cropPlanted != null)
                    {
                        Destroy(cropPlanted.gameObject);
                    }
                    break;
            }
            return;
        }
        SeedData seedTool = toolSlot as SeedData;
        if (seedTool != null && landStatus !=LandStatus.Soil && cropPlanted==null)
        {
            GameObject cropObject =Instantiate(cropPrefab ,transform);
            cropObject.transform.position = new Vector3(transform.position.x,0f,transform.position.z);
            cropPlanted = cropObject.GetComponent<CropBehaviour>();
            cropPlanted.Plant(seedTool);

            //被使用后消失
            InventoryManager.Instance.ConsumeItem(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Tool));
        }
    }

    public void ClockUpdate(GameTimestamp timestamp)
    {
        if (landStatus == LandStatus.Watered)
        {
            int hoursElapsed = GameTimestamp.CompareTimestamp(timeWatered, timestamp);
            if(cropPlanted != null)
            {
                cropPlanted.Grow();
            }
            if (hoursElapsed > 24)
            {
                SwitchLandStatus(LandStatus.Farmland);
            }
        }
        if(landStatus != LandStatus.Watered && cropPlanted != null)
        {
            if(cropPlanted.cropState != CropBehaviour.CropState.Seed)
            {
                cropPlanted.Wilter();
            }
        }
    }
}

6、编辑UIManager.cs,添加StatusBar下显示数量的文本

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

public class UIManager : MonoBehaviour, ITimeTracker
{
    public static UIManager Instance { get; private set; }
    private void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(this); }
        else { Instance = this; }
    }

    [Header("Startas Bar")]
    public Image toolEquipSlotImage;
    public Text toolQuantityText;
    public Text timeText;
    public Text dateText;

    [Header("Inventory System")]

    public GameObject inventoryPanel;
    public HandInventorySlot toolHandSlot;
    public InventorySlot[] toolSlots;
    public HandInventorySlot itemHandSlot;
    public InventorySlot[] itemSlots;

    public Text itemNameText;
    public Text itemDescriptionText;

    private void Start()
    {
        RenderInventory();
        AssignSlotIndex();
        TimeManager.Instance.RegisterTracker(this);
    }
    public void AssignSlotIndex()
    {
        for (int i = 0; i < toolSlots.Length; i++)
        {
            toolSlots[i].AssignIndex(i);
            itemSlots[i].AssignIndex(i);
        }
    }
    public void RenderInventory()
    {
        ItemSlotData[] inventoryToolSlots = InventoryManager.Instance.GetInventorySlots(InventorySlot.InventoryType.Tool);
        ItemSlotData[] inventoryItemSlots = InventoryManager.Instance.GetInventorySlots(InventorySlot.InventoryType.Item);

        RenderInventoryPanel(inventoryToolSlots, toolSlots);
        RenderInventoryPanel(inventoryItemSlots, itemSlots);
        toolHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Tool));
        itemHandSlot.Display(InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Item));
        ItemData equippedTool = InventoryManager.Instance.GetEquippedSlotItem(InventorySlot.InventoryType.Tool);

        //数量文本
        toolQuantityText.text = "";

        if (equippedTool != null)
        {
            toolEquipSlotImage.sprite = equippedTool.thumbnail;
            toolEquipSlotImage.gameObject.SetActive(true);

            //数量文本
            int quantity = InventoryManager.Instance.GetEquippedSlot(InventorySlot.InventoryType.Tool).quantity;
            if (quantity > 1)
            {
                toolQuantityText.text = quantity.ToString();
            }
            return;
        }
        toolEquipSlotImage.gameObject.SetActive(false);
    }
    void RenderInventoryPanel(ItemSlotData[] slots, InventorySlot[] uiSlots)
    {
        for (int i = 0; i < uiSlots.Length; i++)
        {
            uiSlots[i].Display(slots[i]);
        }
    }
    public void ToggleInventoryPanel()
    {
        inventoryPanel.SetActive(!inventoryPanel.activeSelf);
        RenderInventory();
    }

    public void DisplayItemInfo(ItemData data)
    {
        if (data == null)
        {
            itemNameText.text = "";
            itemDescriptionText.text = "";
            return;
        }
        itemNameText.text = data.name;
        itemDescriptionText.text = data.description;
    }
    public void ClockUpdate(GameTimestamp timestamp)
    {
        int hours = timestamp.hour;
        int minutes = timestamp.minute;

        string prefix = "AM ";
        if (hours > 12)
        {
            prefix = "PM ";
            hours -= 12;
        }
        timeText.text = prefix + hours + ":" + minutes.ToString("00");
        int day = timestamp.day;
        string season = timestamp.season.ToString();
        string dayOfTheWeek = timestamp.GetDayOfTheWeek().ToString();

        dateText.text = season + " " + day + " (" + dayOfTheWeek + ")";
    }
}

7、赋值

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值