Tạo hệ thống chế tạo vật phẩm và kho đồ trong Unity

Trong hướng dẫn này, tôi sẽ hướng dẫn cách tạo hệ thống chế tạo vật phẩm và kho đồ kiểu Minecraft trong Unity.

Chế tạo vật phẩm trong trò chơi điện tử là một quá trình kết hợp các vật phẩm cụ thể (thường đơn giản hơn) thành các vật phẩm phức tạp hơn, với các thuộc tính mới và nâng cao. Ví dụ như kết hợp gỗ và đá thành một cái cuốc, hoặc kết hợp tấm kim loại và gỗ thành một thanh kiếm.

Hệ thống chế tạo bên dưới là thân thiện với thiết bị di động và hoàn toàn tự động, nghĩa là nó sẽ hoạt động với mọi bố cục giao diện người dùng và có khả năng tạo các công thức chế tạo tùy chỉnh.

Sharp Coder Trình phát video

Bước 1: Thiết lập giao diện người dùng chế tạo

Chúng tôi bắt đầu bằng cách thiết lập giao diện người dùng chế tạo:

  • Tạo Canvas mới (Unity Thanh tác vụ hàng đầu: GameObject -> UI -> Canvas)
  • Tạo Hình ảnh mới bằng cách Nhấp chuột phải vào Đối tượng Canvas -> Giao diện người dùng -> Hình ảnh
  • Đổi tên Đối tượng hình ảnh thành "CraftingPanel" và thay đổi Hình ảnh nguồn của nó thành mặc định "UISprite"
  • Thay đổi giá trị "CraftingPanel" RectTransform thành (Pos X: 0 Pos Y: 0 Chiều rộng: 410 Chiều cao: 365)

  • Tạo hai Đối tượng bên trong "CraftingPanel" (Nhấp chuột phải vào CraftingPanel -> Tạo sản phẩm trống, 2 lần)
  • Đổi tên Đối tượng đầu tiên thành "CraftingSlots" và thay đổi giá trị RectTransform của nó thành ("Căn chỉnh trên cùng bên trái" Pivot X: 0 Pivot Y: 1 Pos X: 50 Pos Y: -35 Chiều rộng: 140 Chiều cao: 140). Đối tượng này sẽ chứa các khe chế tạo.
  • Đổi tên Đối tượng thứ hai thành "PlayerSlots" và thay đổi giá trị RectTransform của nó thành ("Top Stretchly" Pivot X: 0,5 Pivot Y: 1 Left: 0 Pos Y: -222 Right: 0 Height: 100). Đối tượng này sẽ chứa các vị trí người chơi.

Tiêu đề phần:

  • Tạo văn bản mới bằng cách nhấp chuột phải vào "PlayerSlots" Object -> UI -> Text và đổi tên thành "SectionTitle"
  • Thay đổi giá trị "SectionTitle" RectTransform thành ("Căn chỉnh trên cùng bên trái" Trục X: 0 Trục Y: 0 Pos X: 5 Pos Y: 0 Chiều rộng: 160 Chiều cao: 30)
  • Thay đổi văn bản "SectionTitle" thành "Inventory" và đặt Cỡ chữ thành 18, Căn chỉnh sang Giữa bên trái và Màu thành (0,2, 0,2, 0,2, 1)
  • Nhân đôi Đối tượng "SectionTitle", thay đổi Văn bản của nó thành "Crafting" và di chuyển nó dưới Đối tượng "CraftingSlots", sau đó đặt các giá trị RectTransform giống như "SectionTitle" trước đó.

Khe chế tạo:

Vị trí chế tạo sẽ bao gồm hình nền, hình ảnh vật phẩm và văn bản đếm:

  • Tạo Hình ảnh mới bằng cách Nhấp chuột phải vào Đối tượng Canvas -> Giao diện người dùng -> Hình ảnh
  • Đổi tên Hình ảnh mới thành "slot_template", đặt giá trị RectTransform của nó thành (Đăng X: 0 Pos Y: 0 Chiều rộng: 40 Chiều cao: 40) và thay đổi màu của nó thành (0,32, 0,32, 0,32, 0,8)
  • Nhân đôi "slot_template" và đổi tên thành "Item", di chuyển nó vào trong đối tượng "slot_template", thay đổi kích thước RectTransform của nó thành (Width: 30 Height: 30) và Color thành (1, 1, 1, 1)
  • Tạo văn bản mới bằng cách nhấp chuột phải vào "slot_template" Object -> UI -> Text và đổi tên thành "Count"
  • Thay đổi giá trị "Count" RectTransform thành ("Căn chỉnh dưới cùng bên phải" Pivot X: 1 Pivot Y: 0 Pos X: 0 Pos Y: 0 Chiều rộng: 30 Chiều cao: 30)
  • Đặt "Count" Văn bản thành một số ngẫu nhiên (ví dụ: 12), Kiểu phông chữ thành đậm, Cỡ chữ thành 14, Căn chỉnh thành dưới cùng bên phải và Màu sắc thành (1, 1, 1, 1)
  • Thêm thành phần Shadow vào "Count" Text và đặt Màu hiệu ứng thành (0, 0, 0, 0,5)

Kết quả cuối cùng sẽ trông như thế này:

Khe kết quả (Sẽ được sử dụng để tạo kết quả):

  • Nhân đôi đối tượng "slot_template" và đổi tên thành "result_slot_template"
  • Thay đổi Chiều rộng và Chiều cao của "result_slot_template" thành 50

Nút chế tạo và đồ họa bổ sung:

  • Tạo Nút mới bằng cách Nhấp chuột phải vào "CraftingSlots" Đối tượng -> Giao diện người dùng -> Nút và đổi tên thành "CraftButton"
  • Đặt các giá trị "CraftButton" RectTransform thành ("Căn giữa bên trái" Trục X: 1 Trục Y: 0,5 Pos X: 0 Pos Y: 0 Chiều rộng: 40 Chiều cao: 40)
  • Thay đổi văn bản của "CraftButton" thành "Craft"

  • Tạo một Hình ảnh mới bằng cách Nhấp chuột phải vào "CraftingSlots" Đối tượng -> Giao diện người dùng -> Hình ảnh và đổi tên thành "Arrow"
  • Đặt các giá trị "Arrow" RectTransform thành ("Căn giữa bên phải" Trục X: 0 Trục Y: 0,5 Pos X: 10 Pos Y: 0 Chiều rộng: 30 Chiều cao: 30)

Đối với Hình ảnh nguồn, bạn có thể sử dụng hình ảnh bên dưới (Click chuột phải -> Save as.. để tải xuống). Sau khi nhập, đặt loại Kết cấu thành "Sprite (2D and UI)" và Chế độ lọc thành "Point (no filter)"

Pixel biểu tượng mũi tên bên phải

  • Click chuột phải vào "CraftingSlots" -> Create Empty và đổi tên thành "ResultSlot", đối tượng này sẽ chứa slot kết quả
  • Đặt các giá trị "ResultSlot" RectTransform thành ("Căn giữa bên phải" Trục X: 0 Trục Y: 0,5 Pos X: 50 Pos Y: 0 Chiều rộng: 50 Chiều cao: 50)

Thiết lập giao diện người dùng đã sẵn sàng.

Bước 2: Hệ thống xây dựng chương trình

Hệ thống chế tạo này sẽ bao gồm 2 tập lệnh là SC_ItemCrafting.cs và SC_SlotTemplate.cs

  • Tạo một tập lệnh mới, đặt tên là "SC_ItemCrafting" rồi dán đoạn mã bên dưới vào trong tập lệnh đó:

SC_ItemCrafting.cs

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

public class SC_ItemCrafting : MonoBehaviour
{
    public RectTransform playerSlotsContainer;
    public RectTransform craftingSlotsContainer;
    public RectTransform resultSlotContainer;
    public Button craftButton;
    public SC_SlotTemplate slotTemplate;
    public SC_SlotTemplate resultSlotTemplate;

    [System.Serializable]
    public class SlotContainer
    {
        public Sprite itemSprite; //Sprite of the assigned item (Must be the same sprite as in items array), or leave null for no item
        public int itemCount; //How many items in this slot, everything equal or under 1 will be interpreted as 1 item
        [HideInInspector]
        public int tableID;
        [HideInInspector]
        public SC_SlotTemplate slot;
    }

    [System.Serializable]
    public class Item
    {
        public Sprite itemSprite;
        public bool stackable = false; //Can this item be combined (stacked) together?
        public string craftRecipe; //Item Keys that are required to craft this item, separated by comma (Tip: Use Craft Button in Play mode and see console for printed recipe)
    }

    public SlotContainer[] playerSlots;
    SlotContainer[] craftSlots = new SlotContainer[9];
    SlotContainer resultSlot = new SlotContainer();
    //List of all available items
    public Item[] items;

    SlotContainer selectedItemSlot = null;

    int craftTableID = -1; //ID of table where items will be placed one at a time (ex. Craft table)
    int resultTableID = -1; //ID of table from where we can take items, but cannot place to

    ColorBlock defaultButtonColors;

    // Start is called before the first frame update
    void Start()
    {
        //Setup slot element template
        slotTemplate.container.rectTransform.pivot = new Vector2(0, 1);
        slotTemplate.container.rectTransform.anchorMax = slotTemplate.container.rectTransform.anchorMin = new Vector2(0, 1);
        slotTemplate.craftingController = this;
        slotTemplate.gameObject.SetActive(false);
        //Setup result slot element template
        resultSlotTemplate.container.rectTransform.pivot = new Vector2(0, 1);
        resultSlotTemplate.container.rectTransform.anchorMax = resultSlotTemplate.container.rectTransform.anchorMin = new Vector2(0, 1);
        resultSlotTemplate.craftingController = this;
        resultSlotTemplate.gameObject.SetActive(false);

        //Attach click event to craft button
        craftButton.onClick.AddListener(PerformCrafting);
        //Save craft button default colors
        defaultButtonColors = craftButton.colors;

        //InitializeItem Crafting Slots
        InitializeSlotTable(craftingSlotsContainer, slotTemplate, craftSlots, 5, 0);
        UpdateItems(craftSlots);
        craftTableID = 0;

        //InitializeItem Player Slots
        InitializeSlotTable(playerSlotsContainer, slotTemplate, playerSlots, 5, 1);
        UpdateItems(playerSlots);

        //InitializeItemResult Slot
        InitializeSlotTable(resultSlotContainer, resultSlotTemplate, new SlotContainer[] { resultSlot }, 0, 2);
        UpdateItems(new SlotContainer[] { resultSlot });
        resultTableID = 2;

        //Reset Slot element template (To be used later for hovering element)
        slotTemplate.container.rectTransform.pivot = new Vector2(0.5f, 0.5f);
        slotTemplate.container.raycastTarget = slotTemplate.item.raycastTarget = slotTemplate.count.raycastTarget = false;
    }

    void InitializeSlotTable(RectTransform container, SC_SlotTemplate slotTemplateTmp, SlotContainer[] slots, int margin, int tableIDTmp)
    {
        int resetIndex = 0;
        int rowTmp = 0;
        for (int i = 0; i < slots.Length; i++)
        {
            if (slots[i] == null)
            {
                slots[i] = new SlotContainer();
            }
            GameObject newSlot = Instantiate(slotTemplateTmp.gameObject, container.transform);
            slots[i].slot = newSlot.GetComponent<SC_SlotTemplate>();
            slots[i].slot.gameObject.SetActive(true);
            slots[i].tableID = tableIDTmp;

            float xTmp = (int)((margin + slots[i].slot.container.rectTransform.sizeDelta.x) * (i - resetIndex));
            if (xTmp + slots[i].slot.container.rectTransform.sizeDelta.x + margin > container.rect.width)
            {
                resetIndex = i;
                rowTmp++;
                xTmp = 0;
            }
            slots[i].slot.container.rectTransform.anchoredPosition = new Vector2(margin + xTmp, -margin - ((margin + slots[i].slot.container.rectTransform.sizeDelta.y) * rowTmp));
        }
    }

    //Update Table UI
    void UpdateItems(SlotContainer[] slots)
    {
        for (int i = 0; i < slots.Length; i++)
        {
            Item slotItem = FindItem(slots[i].itemSprite);
            if (slotItem != null)
            {
                if (!slotItem.stackable)
                {
                    slots[i].itemCount = 1;
                }
                //Apply total item count
                if (slots[i].itemCount > 1)
                {
                    slots[i].slot.count.enabled = true;
                    slots[i].slot.count.text = slots[i].itemCount.ToString();
                }
                else
                {
                    slots[i].slot.count.enabled = false;
                }
                //Apply item icon
                slots[i].slot.item.enabled = true;
                slots[i].slot.item.sprite = slotItem.itemSprite;
            }
            else
            {
                slots[i].slot.count.enabled = false;
                slots[i].slot.item.enabled = false;
            }
        }
    }

    //Find Item from the items list using sprite as reference
    Item FindItem(Sprite sprite)
    {
        if (!sprite)
            return null;

        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].itemSprite == sprite)
            {
                return items[i];
            }
        }

        return null;
    }

    //Find Item from the items list using recipe as reference
    Item FindItem(string recipe)
    {
        if (recipe == "")
            return null;

        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].craftRecipe == recipe)
            {
                return items[i];
            }
        }

        return null;
    }

    //Called from SC_SlotTemplate.cs
    public void ClickEventRecheck()
    {
        if (selectedItemSlot == null)
        {
            //Get clicked slot
            selectedItemSlot = GetClickedSlot();
            if (selectedItemSlot != null)
            {
                if (selectedItemSlot.itemSprite != null)
                {
                    selectedItemSlot.slot.count.color = selectedItemSlot.slot.item.color = new Color(1, 1, 1, 0.5f);
                }
                else
                {
                    selectedItemSlot = null;
                }
            }
        }
        else
        {
            SlotContainer newClickedSlot = GetClickedSlot();
            if (newClickedSlot != null)
            {
                bool swapPositions = false;
                bool releaseClick = true;

                if (newClickedSlot != selectedItemSlot)
                {
                    //We clicked on the same table but different slots
                    if (newClickedSlot.tableID == selectedItemSlot.tableID)
                    {
                        //Check if new clicked item is the same, then stack, if not, swap (Unless it's a crafting table, then do nothing)
                        if (newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                        {
                            Item slotItem = FindItem(selectedItemSlot.itemSprite);
                            if (slotItem.stackable)
                            {
                                //Item is the same and is stackable, remove item from previous position and add its count to a new position
                                selectedItemSlot.itemSprite = null;
                                newClickedSlot.itemCount += selectedItemSlot.itemCount;
                                selectedItemSlot.itemCount = 0;
                            }
                            else
                            {
                                swapPositions = true;
                            }
                        }
                        else
                        {
                            swapPositions = true;
                        }
                    }
                    else
                    {
                        //Moving to different table
                        if (resultTableID != newClickedSlot.tableID)
                        {
                            if (craftTableID != newClickedSlot.tableID)
                            {
                                if (newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                                {
                                    Item slotItem = FindItem(selectedItemSlot.itemSprite);
                                    if (slotItem.stackable)
                                    {
                                        //Item is the same and is stackable, remove item from previous position and add its count to a new position
                                        selectedItemSlot.itemSprite = null;
                                        newClickedSlot.itemCount += selectedItemSlot.itemCount;
                                        selectedItemSlot.itemCount = 0;
                                    }
                                    else
                                    {
                                        swapPositions = true;
                                    }
                                }
                                else
                                {
                                    swapPositions = true;
                                }
                            }
                            else
                            {
                                if (newClickedSlot.itemSprite == null || newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                                {
                                    //Add 1 item from selectedItemSlot
                                    newClickedSlot.itemSprite = selectedItemSlot.itemSprite;
                                    newClickedSlot.itemCount++;
                                    selectedItemSlot.itemCount--;
                                    if (selectedItemSlot.itemCount <= 0)
                                    {
                                        //We placed the last item
                                        selectedItemSlot.itemSprite = null;
                                    }
                                    else
                                    {
                                        releaseClick = false;
                                    }
                                }
                                else
                                {
                                    swapPositions = true;
                                }
                            }
                        }
                    }
                }

                if (swapPositions)
                {
                    //Swap items
                    Sprite previousItemSprite = selectedItemSlot.itemSprite;
                    int previousItemConunt = selectedItemSlot.itemCount;

                    selectedItemSlot.itemSprite = newClickedSlot.itemSprite;
                    selectedItemSlot.itemCount = newClickedSlot.itemCount;

                    newClickedSlot.itemSprite = previousItemSprite;
                    newClickedSlot.itemCount = previousItemConunt;
                }

                if (releaseClick)
                {
                    //Release click
                    selectedItemSlot.slot.count.color = selectedItemSlot.slot.item.color = Color.white;
                    selectedItemSlot = null;
                }

                //Update UI
                UpdateItems(playerSlots);
                UpdateItems(craftSlots);
                UpdateItems(new SlotContainer[] { resultSlot });
            }
        }
    }

    SlotContainer GetClickedSlot()
    {
        for (int i = 0; i < playerSlots.Length; i++)
        {
            if (playerSlots[i].slot.hasClicked)
            {
                playerSlots[i].slot.hasClicked = false;
                return playerSlots[i];
            }
        }

        for (int i = 0; i < craftSlots.Length; i++)
        {
            if (craftSlots[i].slot.hasClicked)
            {
                craftSlots[i].slot.hasClicked = false;
                return craftSlots[i];
            }
        }

        if (resultSlot.slot.hasClicked)
        {
            resultSlot.slot.hasClicked = false;
            return resultSlot;
        }

        return null;
    }

    void PerformCrafting()
    {
        string[] combinedItemRecipe = new string[craftSlots.Length];

        craftButton.colors = defaultButtonColors;

        for (int i = 0; i < craftSlots.Length; i++)
        {
            Item slotItem = FindItem(craftSlots[i].itemSprite);
            if (slotItem != null)
            {
                combinedItemRecipe[i] = slotItem.itemSprite.name + (craftSlots[i].itemCount > 1 ? "(" + craftSlots[i].itemCount + ")" : "");
            }
            else
            {
                combinedItemRecipe[i] = "";
            }
        }

        string combinedRecipe = string.Join(",", combinedItemRecipe);
        print(combinedRecipe);

        //Search if recipe match any of the item recipe
        Item craftedItem = FindItem(combinedRecipe);
        if (craftedItem != null)
        {
            //Clear Craft slots
            for (int i = 0; i < craftSlots.Length; i++)
            {
                craftSlots[i].itemSprite = null;
                craftSlots[i].itemCount = 0;
            }

            resultSlot.itemSprite = craftedItem.itemSprite;
            resultSlot.itemCount = 1;

            UpdateItems(craftSlots);
            UpdateItems(new SlotContainer[] { resultSlot });
        }
        else
        {
            ColorBlock colors = craftButton.colors;
            colors.selectedColor = colors.pressedColor = new Color(0.8f, 0.55f, 0.55f, 1);
            craftButton.colors = colors;
        }
    }

    // Update is called once per frame
    void Update()
    {
        //Slot UI follow mouse position
        if (selectedItemSlot != null)
        {
            if (!slotTemplate.gameObject.activeSelf)
            {
                slotTemplate.gameObject.SetActive(true);
                slotTemplate.container.enabled = false;

                //Copy selected item values to slot template
                slotTemplate.count.color = selectedItemSlot.slot.count.color;
                slotTemplate.item.sprite = selectedItemSlot.slot.item.sprite;
                slotTemplate.item.color = selectedItemSlot.slot.item.color;
            }

            //Make template slot follow mouse position
            slotTemplate.container.rectTransform.position = Input.mousePosition;
            //Update item count
            slotTemplate.count.text = selectedItemSlot.slot.count.text;
            slotTemplate.count.enabled = selectedItemSlot.slot.count.enabled;
        }
        else
        {
            if (slotTemplate.gameObject.activeSelf)
            {
                slotTemplate.gameObject.SetActive(false);
            }
        }
    }
}
  • Tạo một tập lệnh mới, đặt tên là "SC_SlotTemplate" rồi dán đoạn mã bên dưới vào trong tập lệnh đó:

SC_SlotTemplate.cs

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

public class SC_SlotTemplate : MonoBehaviour, IPointerClickHandler
{
    public Image container;
    public Image item;
    public Text count;

    [HideInInspector]
    public bool hasClicked = false;
    [HideInInspector]
    public SC_ItemCrafting craftingController;

    //Do this when the mouse is clicked over the selectable object this script is attached to.
    public void OnPointerClick(PointerEventData eventData)
    {
        hasClicked = true;
        craftingController.ClickEventRecheck();
    }
}

Chuẩn bị các mẫu slot:

  • Đính kèm tập lệnh SC_SlotTemplate vào đối tượng "slot_template" và gán các biến của nó (Thành phần hình ảnh trên cùng một Đối tượng sẽ chuyển đến biến "Container", Hình ảnh con "Item" chuyển đến biến "Item" và một con "Count" Văn bản chuyển đến biến "Count")
  • Lặp lại quy trình tương tự cho Đối tượng "result_slot_template" (đính kèm tập lệnh SC_SlotTemplate vào nó và gán các biến theo cách tương tự).

Chuẩn bị hệ thống thủ công:

  • Đính kèm tập lệnh SC_ItemCrafting vào đối tượng Canvas và gán các biến của nó Đối tượng ("PlayerSlots" chuyển đến biến "Player Slots Container", "CraftingSlots" Đối tượng chuyển đến biến "Crafting Slots Container", "ResultSlot" Đối tượng chuyển đến "Result Slot Container" biến, "CraftButton" Đối tượng chuyển đến biến "Craft Button", "slot_template" Đối tượng có tập lệnh SC_SlotTemplate được đính kèm sẽ chuyển đến biến "Slot Template" và Đối tượng "result_slot_template" có tập lệnh SC_SlotTemplate được đính kèm sẽ chuyển đến biến "Result Slot Template"):

Như bạn đã nhận thấy, có hai mảng trống có tên "Player Slots" và "Items". "Player Slots" sẽ chứa số lượng vị trí có sẵn (có Vật phẩm hoặc trống) và "Items" sẽ chứa tất cả các vật phẩm có sẵn cùng với công thức nấu ăn của chúng (tùy chọn).

Thiết lập các mục:

Kiểm tra các sprite bên dưới (trong trường hợp của tôi, tôi sẽ có 5 mục):

Vật phẩm bằng đá (đá)

Vật phẩm kim cương (kim cương)

Mặt hàng gỗ (gỗ)

Vật phẩm kiếm (thanh kiếm)

Thanh kiếm kim cương (kim cương_kiếm)

  • Tải xuống từng sprite (Nhấp chuột phải -> Lưu dưới dạng...) và nhập chúng vào dự án của bạn (Trong Cài đặt nhập, đặt Loại họa tiết của chúng thành "Sprite (2D and UI)" và Chế độ lọc thành "Point (no filter)"

  • Trong SC_ItemCrafting thay đổi Kích thước vật phẩm thành 5 và gán mỗi sprite cho biến Item Sprite.

"Stackable" biến kiểm soát xem các vật phẩm có thể được xếp chồng lên nhau vào một khe hay không (ví dụ: bạn có thể chỉ muốn cho phép xếp chồng các vật liệu đơn giản như đá, kim cương và gỗ).

"Craft Recipe" điều khiển thay đổi nếu vật phẩm này có thể được chế tạo (trống có nghĩa là không thể chế tạo được)

  • Đối với "Player Slots", đặt Kích thước mảng thành 27 (phù hợp nhất với Bảng chế tạo hiện tại, nhưng bạn có thể đặt bất kỳ số nào).

Khi nhấn Play, bạn sẽ nhận thấy rằng các ô được khởi tạo chính xác nhưng không có mục nào:

Để thêm một mục vào mỗi vị trí, chúng ta cần gán một mục Sprite cho biến "Item Sprite" và đặt "Item Count" thành bất kỳ số dương nào (mọi thứ dưới 1 và/hoặc các mục không thể xếp chồng sẽ được hiểu là 1):

  • Gán sprite "rock" cho Phần tử 0 / "Item Count" 14, sprite "wood" cho Phần tử 1 / "Item Count" 8, "diamond" sprite cho Phần tử 2 / "Item Count" 8 (Đảm bảo các sprite giống như trong "Items" Array, nếu không nó sẽ không hoạt động).

Các vật phẩm bây giờ sẽ xuất hiện trong Player Slots, bạn có thể thay đổi vị trí của chúng bằng cách nhấp vào vật phẩm đó, sau đó nhấp vào vị trí bạn muốn di chuyển nó đến.

Bí quyết chế tạo:

Công thức chế tạo cho phép bạn tạo một vật phẩm bằng cách kết hợp các vật phẩm khác theo một thứ tự cụ thể:

Định dạng cho công thức chế tạo như sau: [item_sprite_name]([item count])*không bắt buộc... lặp lại 9 lần, cách nhau bằng dấu phẩy (,)

Một cách dễ dàng để khám phá công thức là nhấn Play, sau đó đặt các vật phẩm theo thứ tự bạn muốn chế tạo, sau đó nhấn "Craft", sau đó nhấn (Ctrl + Shift + C) để mở Unity Console và xem dòng mới in (Bạn có thể bấm "Craft" nhiều lần để in lại dòng), dòng in ra chính là công thức chế tạo.

Ví dụ: sự kết hợp bên dưới tương ứng với công thức này: rock,,rock,,rock,,rock,,wood (LƯU Ý: nó có thể khác đối với bạn nếu các nhân vật của bạn có tên khác).

Công thức chế tạo vật phẩm kiếm

Chúng ta sẽ sử dụng công thức trên để chế tạo một thanh kiếm.

  • Sao chép dòng đã in và trong Mảng "Items" dán nó vào biến "Craft Recipe" bên dưới "sword" Mục:

Bây giờ, khi lặp lại sự kết hợp đó, bạn sẽ có thể tạo ra một thanh kiếm.

Công thức chế tạo một thanh kiếm kim cương cũng giống như vậy, nhưng thay vì đá thì đó là kim cương:

Công thức kiếm vật phẩm kim cương Thanh tra thống nhất

Hệ thống kiểm kê Unity và chế tạo vật phẩm

Hệ thống chế tạo hiện đã sẵn sàng.

Nguồn
📁ItemCrafting.unitypackage36.13 KB
Bài viết được đề xuất
Mã hóa một hệ thống kiểm kê đơn giản bằng tính năng kéo và thả giao diện người dùng trong Unity
Cách kích hoạt đoạn cắt cảnh trong Unity
Giới thiệu về State Machine trong Unity
Tạo đồ sưu tầm và tăng sức mạnh trong Unity
Tạo trò chơi lấy cảm hứng từ Pac-Man trong Unity
Tạo hệ thống đạn 2D đơn giản trong Unity
Tạo bộ điều khiển tháp pháo trong Unity